summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMayank Prasad <mayank.prasad@oracle.com>2011-05-18 20:10:01 +0530
committerMayank Prasad <mayank.prasad@oracle.com>2011-05-18 20:10:01 +0530
commit55d3381cc7bdde44d7f040921e5df1d7c229b846 (patch)
tree4cce2b7b8458e61ce73aefc6a834029bf0860901
parenta7cd008e12875d21d37ae92ccbef50d87d4fbd35 (diff)
downloadmariadb-git-55d3381cc7bdde44d7f040921e5df1d7c229b846.tar.gz
Bug#11764633 : 57491: THD->MAIN_DA.IS_OK() ASSERT IN EMBEDDED
Issue: While running embedded server, if client issues TEE command (\T foo/bar) and "foo/bar" directory doesn't exist, it is suppose to give error. But it was aborting. This was happening because wrong error handler was being called. Solution: Modified calls to correct error handler. In embedded server case, there are two error handler (client and server) which are supposed to be called based on which context code is in. If it is in client context, client error handler should be called otherwise server. Test case: Test case automation is not possible as current (following) code doesn't allow '\T' to be executed from command line (OR command read from a file): [client/mysql.cc] ... static int com_tee(String *buffer __attribute__((unused)), char *line __attribute__((unused))) { char file_name[FN_REFLEN], *end, *param; if (status.batch) << THIS IS TRUE WHILE EXECUTING FROM COMMAND LINE. return 0; ... So, not adding test case in GA. WIll add a test case in mysql-trunk after removing above code so that this could be properly tested before GA.
-rw-r--r--libmysqld/lib_sql.cc28
-rw-r--r--sql/mysql_priv.h8
-rw-r--r--sql/sql_class.cc19
-rw-r--r--sql/sql_class.h1
4 files changed, 54 insertions, 2 deletions
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 778d4874ad4..b6da6172039 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -51,6 +51,23 @@ extern "C" void unireg_clear(int exit_code)
DBUG_VOID_RETURN;
}
+/*
+ Wrapper error handler for embedded server to call client/server error
+ handler based on whether thread is in client/server context
+*/
+
+static int embedded_error_handler(uint error, const char *str, myf MyFlags)
+{
+ DBUG_ENTER("embedded_error_handler");
+
+ /*
+ If current_thd is NULL, it means restore_global has been called and
+ thread is in client context, then call client error handler else call
+ server error handler.
+ */
+ DBUG_RETURN(current_thd ? my_message_sql(error, str, MyFlags):
+ my_message_no_curses(error, str, MyFlags));
+}
/*
Reads error information from the MYSQL_DATA and puts
@@ -107,7 +124,8 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
if (mysql->status != MYSQL_STATUS_READY)
{
set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
- return 1;
+ result= 1;
+ goto end;
}
/* Clear result variables */
@@ -147,6 +165,9 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.finish_current_query();
#endif
+
+end:
+ thd->restore_globals();
return result;
}
@@ -525,7 +546,10 @@ int init_embedded_server(int argc, char **argv, char **groups)
return 1;
}
- error_handler_hook = my_message_sql;
+ /*
+ set error_handler_hook to embedded_error_handler wrapper.
+ */
+ error_handler_hook= embedded_error_handler;
acl_error= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 8f9a9080d12..3ce73291206 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -670,6 +670,10 @@ enum enum_check_fields
extern "C" THD *_current_thd_noinline();
#define _current_thd() _current_thd_noinline()
#else
+/*
+ THR_THD is a key which will be used to set/get THD* for a thread,
+ using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr().
+*/
extern pthread_key(THD*, THR_THD);
inline THD *_current_thd(void)
{
@@ -2022,6 +2026,10 @@ extern TABLE_LIST general_log, slow_log;
extern FILE *bootstrap_file;
extern int bootstrap_error;
extern FILE *stderror_file;
+/*
+ THR_MALLOC is a key which will be used to set/get MEM_ROOT** for a thread,
+ using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr().
+*/
extern pthread_key(MEM_ROOT**,THR_MALLOC);
extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open, LOCK_lock_db,
LOCK_mapped_file,LOCK_user_locks, LOCK_status,
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ae21a5335fd..04f981c6d6a 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1196,6 +1196,25 @@ bool THD::store_globals()
return 0;
}
+/*
+ Remove the thread specific info (THD and mem_root pointer) stored during
+ store_global call for this thread.
+*/
+bool THD::restore_globals()
+{
+ /*
+ Assert that thread_stack is initialized: it's necessary to be able
+ to track stack overrun.
+ */
+ DBUG_ASSERT(thread_stack);
+
+ /* Undocking the thread specific data. */
+ my_pthread_setspecific_ptr(THR_THD, NULL);
+ my_pthread_setspecific_ptr(THR_MALLOC, NULL);
+
+ return 0;
+}
+
/*
Cleanup after query.
diff --git a/sql/sql_class.h b/sql/sql_class.h
index b3e8fde8cda..6b82512677a 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1943,6 +1943,7 @@ public:
void cleanup(void);
void cleanup_after_query();
bool store_globals();
+ bool restore_globals();
#ifdef SIGNAL_WITH_VIO_CLOSE
inline void set_active_vio(Vio* vio)
{