[This commit e-mail is a repeat.]
#At file:///home/mayank/mysql-tree/mydefects/5.1_11764633_3/ based on
revid:karen.langford@stripped
3685 Mayank Prasad 2011-05-09
Bug#11764633 : 57491: THD->MAIN_DA.IS_OK() ASSERT IN EMBEDDED
Issue:
TEE command '\T foo/bar' was aborting. This is because, foo/bar
directory doesn't exist. To report this error, server error handler was
invoked and diagnostic area was found not reset. So abort was happenning.
Solution:
Call server/client error handler based on if control is in server/client
code respectively.
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.
@ libmysqld/lib_sql.cc
Added code to call client/server error handler based on in control is in
client/server code respectively.
@ sql/mysql_priv.h
Added comments for THR_THD, THR_MALLOC keys.
@ sql/sql_class.cc
Function definition of new function restore_global to removes thread specific data
from stack (which was stored in store global).
@ sql/sql_class.h
Function declaration of new function restore_global.
modified:
libmysqld/lib_sql.cc
sql/mysql_priv.h
sql/sql_class.cc
sql/sql_class.h
=== modified file 'libmysqld/lib_sql.cc'
--- a/libmysqld/lib_sql.cc 2009-12-18 18:44:24 +0000
+++ b/libmysqld/lib_sql.cc 2011-05-09 10:17:49 +0000
@@ -41,7 +41,17 @@ C_MODE_START
extern unsigned int mysql_server_last_errno;
extern char mysql_server_last_error[MYSQL_ERRMSG_SIZE];
static my_bool emb_read_query_result(MYSQL *mysql);
-
+/*
+ Wrapper error handler 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);
+/*
+ Pointer to client error handler. It gets assigned in init_embedded_server.
+ It is used to call client error handling routine in embedded_error_handler.
+*/
+static int (*client_error_handler_hook)(uint my_err, const char *str,
+ myf MyFlags);
extern "C" void unireg_clear(int exit_code)
{
@@ -51,6 +61,23 @@ extern "C" void unireg_clear(int exit_co
DBUG_VOID_RETURN;
}
+/*
+ Wrapper error handler for embedded server. Based on thread's state, call
+ the error handler accordingly.
+*/
+
+int embedded_error_handler(uint error, const char *str, myf MyFlags)
+{
+ DBUG_ENTER("embedded_error_handler");
+
+ /*
+ If _current_thd() returns 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):
+ client_error_handler_hook(error, str, MyFlags));
+}
/*
Reads error information from the MYSQL_DATA and puts
@@ -107,7 +134,8 @@ emb_advanced_command(MYSQL *mysql, enum
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 +175,9 @@ emb_advanced_command(MYSQL *mysql, enum
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.finish_current_query();
#endif
+
+end:
+ thd->restore_globals();
return result;
}
@@ -525,7 +556,12 @@ int init_embedded_server(int argc, char
return 1;
}
- error_handler_hook = my_message_sql;
+ /*
+ store the client error handler hook and set error handler to
+ embedded_error_handler_hook wrapper.
+ */
+ client_error_handler_hook= error_handler_hook;
+ error_handler_hook= embedded_error_handler;
acl_error= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2011-03-15 11:36:12 +0000
+++ b/sql/mysql_priv.h 2011-05-09 10:17:49 +0000
@@ -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,
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2011-04-07 18:12:54 +0000
+++ b/sql/sql_class.cc 2011-05-09 10:17:49 +0000
@@ -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.
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2011-02-22 21:03:32 +0000
+++ b/sql/sql_class.h 2011-05-09 10:17:49 +0000
@@ -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)
{
Attachment: [text/bzr-bundle] bzr/mayank.prasad@oracle.com-20110509101749-qm1j9j5knu0jbfqq.bundle
| Thread |
|---|
| • [Resend] bzr commit into mysql-5.1 branch (mayank.prasad:3685) Bug#11764633 | Mayank Prasad | 9 May |