#At file:///home/mayank/mysql-tree/mydefects/5.1_11764633_2/ based on revid:sergey.glukhov@stripped
3640 Mayank Prasad 2011-04-11
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.
PS: need to add a test case fot the issue. Working on it.
@ include/my_pthread.h
Added a flag to indicate if control is in server code.
@ libmysqld/lib_sql.cc
Added code to call server/client error handler according to flag my_thread_var->is_in_server_code value.
modified:
include/my_pthread.h
libmysqld/lib_sql.cc
=== modified file 'include/my_pthread.h'
--- a/include/my_pthread.h 2011-02-22 21:03:32 +0000
+++ b/include/my_pthread.h 2011-04-11 03:33:23 +0000
@@ -695,6 +695,7 @@ struct st_my_thread_var
void *dbug;
char name[THREAD_NAME_SIZE+1];
#endif
+ my_bool is_in_server_code;
};
extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
=== modified file 'libmysqld/lib_sql.cc'
--- a/libmysqld/lib_sql.cc 2009-12-18 18:44:24 +0000
+++ b/libmysqld/lib_sql.cc 2011-04-11 03:33:23 +0000
@@ -22,6 +22,12 @@
#define main main1
#define mysql_unix_port mysql_inix_port1
#define mysql_port mysql_port1
+#define SET_THREAD_STATE_IN_SERVER_CODE \
+ my_thread_var->is_in_server_code = 1;
+#define RESET_THREAD_STATE_IN_SERVER_CODE \
+ my_thread_var->is_in_server_code = 0;
+#define IS_THREAD_STATE_IN_SERVER_CODE \
+ my_thread_var->is_in_server_code
extern "C"
{
@@ -41,6 +47,8 @@ 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);
+static int embedded_error_handler(uint error, const char *str, myf MyFlags);
+static int (*client_error_handler_hook)(uint my_err, const char *str,myf MyFlags);
extern "C" void unireg_clear(int exit_code)
@@ -51,6 +59,24 @@ extern "C" void unireg_clear(int exit_co
DBUG_VOID_RETURN;
}
+/*
+ Wrapper for error handler for embedded server. Based on thread state, call
+ the error handler accordingly
+*/
+
+int embedded_error_handler(uint error, const char *str, myf MyFlags)
+{
+ DBUG_ENTER("embedded_error_handler");
+
+ /*
+ If thread is in server code, call server error handler
+ else call client error handler
+ */
+ IS_THREAD_STATE_IN_SERVER_CODE ? my_message_sql(error,str,MyFlags):
+ client_error_handler_hook(error,str,MyFlags);
+ DBUG_RETURN(0);
+}
+
/*
Reads error information from the MYSQL_DATA and puts
@@ -86,15 +112,21 @@ emb_advanced_command(MYSQL *mysql, enum
MYSQL_STMT *stmt)
{
my_bool result= 1;
+ my_bool ret_value = 0;
THD *thd=(THD *) mysql->thd;
NET *net= &mysql->net;
my_bool stmt_skip= stmt ? stmt->state != MYSQL_STMT_INIT_DONE : FALSE;
+ SET_THREAD_STATE_IN_SERVER_CODE;
+
if (!thd)
{
/* Do "reconnect" if possible */
if (mysql_reconnect(mysql) || stmt_skip)
- return 1;
+ {
+ ret_value = 1;
+ goto end;
+ }
thd= (THD *) mysql->thd;
}
@@ -107,7 +139,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;
+ ret_value = 1;
+ goto end;
}
/* Clear result variables */
@@ -147,12 +180,17 @@ emb_advanced_command(MYSQL *mysql, enum
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.finish_current_query();
#endif
- return result;
+ ret_value = result;
+
+end:
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_value;
}
static void emb_flush_use_result(MYSQL *mysql)
{
THD *thd= (THD*) mysql->thd;
+ SET_THREAD_STATE_IN_SERVER_CODE;
if (thd->cur_data)
{
free_rows(thd->cur_data);
@@ -164,6 +202,8 @@ static void emb_flush_use_result(MYSQL *
thd->first_data= data->embedded_info->next;
free_rows(data);
}
+
+ RESET_THREAD_STATE_IN_SERVER_CODE;
}
@@ -187,34 +227,52 @@ emb_read_rows(MYSQL *mysql, MYSQL_FIELD
unsigned int fields __attribute__((unused)))
{
MYSQL_DATA *result= ((THD*)mysql->thd)->cur_data;
+ MYSQL_DATA *ret_value = NULL;
((THD*)mysql->thd)->cur_data= 0;
+ SET_THREAD_STATE_IN_SERVER_CODE;
if (result->embedded_info->last_errno)
{
embedded_get_error(mysql, result);
- return NULL;
+ ret_value = NULL;
+ goto end;
}
*result->embedded_info->prev_ptr= NULL;
- return result;
+ ret_value = result;
+
+end:
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_value;
}
static MYSQL_FIELD *emb_list_fields(MYSQL *mysql)
{
MYSQL_DATA *res;
+ MYSQL_FIELD *ret_value = NULL;
+ SET_THREAD_STATE_IN_SERVER_CODE;
if (emb_read_query_result(mysql))
- return 0;
+ {
+ ret_value = 0;
+ goto end;
+ }
res= ((THD*) mysql->thd)->cur_data;
((THD*) mysql->thd)->cur_data= 0;
mysql->field_alloc= res->alloc;
my_free(res,MYF(0));
mysql->status= MYSQL_STATUS_READY;
- return mysql->fields;
+ ret_value = mysql->fields;
+
+end:
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_value;
}
static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
{
THD *thd= (THD*) mysql->thd;
MYSQL_DATA *res;
+ my_bool ret_value = 0;
+ SET_THREAD_STATE_IN_SERVER_CODE;
stmt->stmt_id= thd->client_stmt_id;
stmt->param_count= thd->client_param_count;
@@ -224,7 +282,10 @@ static my_bool emb_read_prepare_result(M
if (thd->first_data)
{
if (emb_read_query_result(mysql))
- return 1;
+ {
+ ret_value = 1;
+ goto end;
+ }
stmt->field_count= mysql->field_count;
mysql->status= MYSQL_STATUS_READY;
res= thd->cur_data;
@@ -238,7 +299,11 @@ static my_bool emb_read_prepare_result(M
my_free(res,MYF(0));
}
- return 0;
+ ret_value = 0;
+
+end:
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_value;
}
/**************************************************************************
@@ -258,15 +323,18 @@ static void emb_fetch_lengths(ulong *to,
static my_bool emb_read_query_result(MYSQL *mysql)
{
+ my_bool ret_value = 0;
THD *thd= (THD*) mysql->thd;
MYSQL_DATA *res= thd->first_data;
DBUG_ASSERT(!thd->cur_data);
+ SET_THREAD_STATE_IN_SERVER_CODE;
thd->first_data= res->embedded_info->next;
if (res->embedded_info->last_errno &&
!res->embedded_info->fields_list)
{
embedded_get_error(mysql, res);
- return 1;
+ ret_value = 1;
+ goto end;
}
mysql->warning_count= res->embedded_info->warning_count;
@@ -294,7 +362,11 @@ static my_bool emb_read_query_result(MYS
else
my_free(res, MYF(0));
- return 0;
+ ret_value = 0;
+
+end:
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_value;
}
static int emb_stmt_execute(MYSQL_STMT *stmt)
@@ -303,6 +375,9 @@ static int emb_stmt_execute(MYSQL_STMT *
uchar header[5];
THD *thd;
my_bool res;
+ int ret_value = 0;
+
+ SET_THREAD_STATE_IN_SERVER_CODE;
int4store(header, stmt->stmt_id);
header[4]= (uchar) stmt->flags;
@@ -320,23 +395,36 @@ static int emb_stmt_execute(MYSQL_STMT *
{
NET *net= &stmt->mysql->net;
set_stmt_errmsg(stmt, net);
- DBUG_RETURN(1);
+ ret_value = 1;
+ goto end;
}
- DBUG_RETURN(0);
+ ret_value = 0;
+
+end:
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ DBUG_RETURN(ret_value);
}
int emb_read_binary_rows(MYSQL_STMT *stmt)
{
MYSQL_DATA *data;
+ int ret_value = 0;
+ SET_THREAD_STATE_IN_SERVER_CODE;
+
if (!(data= emb_read_rows(stmt->mysql, 0, 0)))
{
set_stmt_errmsg(stmt, &stmt->mysql->net);
- return 1;
+ ret_value = 1;
+ goto end;
}
stmt->result= *data;
my_free((char *) data, MYF(0));
set_stmt_errmsg(stmt, &stmt->mysql->net);
- return 0;
+ ret_value = 0;
+
+end:
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_value;
}
int emb_read_rows_from_cursor(MYSQL_STMT *stmt)
@@ -344,13 +432,17 @@ int emb_read_rows_from_cursor(MYSQL_STMT
MYSQL *mysql= stmt->mysql;
THD *thd= (THD*) mysql->thd;
MYSQL_DATA *res= thd->first_data;
+ int ret_value = 0;
+
+ SET_THREAD_STATE_IN_SERVER_CODE;
DBUG_ASSERT(!thd->first_data->embedded_info->next);
thd->first_data= 0;
if (res->embedded_info->last_errno)
{
embedded_get_error(mysql, res);
set_stmt_errmsg(stmt, &mysql->net);
- return 1;
+ ret_value = 1;
+ goto end;
}
thd->cur_data= res;
@@ -358,18 +450,27 @@ int emb_read_rows_from_cursor(MYSQL_STMT
mysql->server_status= res->embedded_info->server_status;
net_clear_error(&mysql->net);
- return emb_read_binary_rows(stmt);
+ ret_value = emb_read_binary_rows(stmt);
+
+end:
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_value;
}
int emb_unbuffered_fetch(MYSQL *mysql, char **row)
{
THD *thd= (THD*) mysql->thd;
MYSQL_DATA *data= thd->cur_data;
+ int ret_value = 0;
+
+ SET_THREAD_STATE_IN_SERVER_CODE;
+
if (data && data->embedded_info->last_errno)
{
embedded_get_error(mysql, data);
thd->cur_data= 0;
- return 1;
+ ret_value = 1;
+ goto end;
}
if (!data || !data->data)
{
@@ -386,12 +487,17 @@ int emb_unbuffered_fetch(MYSQL *mysql, c
*row= (char *)data->data->data;
data->data= data->data->next;
}
- return 0;
+ ret_value = 0;
+
+end:
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_value;
}
static void emb_free_embedded_thd(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
+ SET_THREAD_STATE_IN_SERVER_CODE;
thd->clear_data_list();
thread_count--;
thd->store_globals();
@@ -399,18 +505,27 @@ static void emb_free_embedded_thd(MYSQL
delete thd;
my_pthread_setspecific_ptr(THR_THD, 0);
mysql->thd=0;
+ RESET_THREAD_STATE_IN_SERVER_CODE;
}
static const char * emb_read_statistics(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
- return thd->is_error() ? thd->main_da.message() : "";
+ const char* ret_value = NULL;
+ SET_THREAD_STATE_IN_SERVER_CODE;
+ ret_value = thd->is_error() ? thd->main_da.message() : "";
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_value;
}
static MYSQL_RES * emb_store_result(MYSQL *mysql)
{
- return mysql_store_result(mysql);
+ SET_THREAD_STATE_IN_SERVER_CODE;
+ MYSQL_RES * ret_value = NULL;
+ ret_value = mysql_store_result(mysql);
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_value;
}
int emb_read_change_user_result(MYSQL *mysql,
@@ -480,6 +595,7 @@ int init_embedded_server(int argc, char
char *fake_argv[] = { (char *)"", 0 };
const char *fake_groups[] = { "server", "embedded", 0 };
my_bool acl_error;
+ int ret_code= 0;
if (argc)
{
argcp= &argc;
@@ -504,7 +620,8 @@ int init_embedded_server(int argc, char
if (init_common_variables("my", *argcp, *argvp, (const char **)groups))
{
mysql_server_end();
- return 1;
+ ret_code= 1;
+ goto end;
}
/* Get default temporary directory */
@@ -522,10 +639,17 @@ int init_embedded_server(int argc, char
if (init_server_components())
{
mysql_server_end();
- return 1;
+ ret_code= 1;
+ goto end;
}
- 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;
+ SET_THREAD_STATE_IN_SERVER_CODE;
acl_error= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -536,7 +660,8 @@ int init_embedded_server(int argc, char
if (acl_error || my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
{
mysql_server_end();
- return 1;
+ ret_code= 1;
+ goto end;
}
init_max_user_conn();
@@ -563,12 +688,17 @@ int init_embedded_server(int argc, char
if (read_init_file(opt_init_file))
{
mysql_server_end();
- return 1;
+ ret_code= 1;
+ goto end;
}
}
execute_ddl_log_recovery();
- return 0;
+ ret_code= 0;
+
+end:
+ RESET_THREAD_STATE_IN_SERVER_CODE;
+ return ret_code;
}
void end_embedded_server()
Attachment: [text/bzr-bundle] bzr/mayank.prasad@oracle.com-20110411033323-0qez0ne3qtqi27r8.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1 branch (mayank.prasad:3640) Bug#11764633 | Mayank Prasad | 11 Apr |