Commit 7f38a070 authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-10043 - main.events_restart fails sporadically in buildbot (crashes upon

             shutdown)

There was race condition between shutdown thread and event worker threads.

Shutdown thread waits for thread_count to become 0 in close_connections(). It
may happen so that event worker thread was started but didn't increment
thread_count by this time. In this case shutdown thread may miss wait for this
working thread and continue deinitialization. Worker thread in turn may continue
execution and crash on deinitialized data.

Fixed by incrementing thread_count before thread is actually created like it is
done for connection threads.

Also let event scheduler not to inc/dec running threads counter for symmetry
with other "service" threads.
parent 128930c1
...@@ -131,12 +131,6 @@ post_init_event_thread(THD *thd) ...@@ -131,12 +131,6 @@ post_init_event_thread(THD *thd)
thd->cleanup(); thd->cleanup();
return TRUE; return TRUE;
} }
mysql_mutex_lock(&LOCK_thread_count);
threads.append(thd);
thread_count++;
inc_thread_running();
mysql_mutex_unlock(&LOCK_thread_count);
return FALSE; return FALSE;
} }
...@@ -158,7 +152,6 @@ deinit_event_thread(THD *thd) ...@@ -158,7 +152,6 @@ deinit_event_thread(THD *thd)
DBUG_PRINT("exit", ("Event thread finishing")); DBUG_PRINT("exit", ("Event thread finishing"));
mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_thread_count);
thread_count--; thread_count--;
dec_thread_running();
delete thd; delete thd;
mysql_cond_broadcast(&COND_thread_count); mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count); mysql_mutex_unlock(&LOCK_thread_count);
...@@ -195,6 +188,8 @@ pre_init_event_thread(THD* thd) ...@@ -195,6 +188,8 @@ pre_init_event_thread(THD* thd)
thd->client_capabilities|= CLIENT_MULTI_RESULTS; thd->client_capabilities|= CLIENT_MULTI_RESULTS;
mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_thread_count);
thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
threads.append(thd);
thread_count++;
mysql_mutex_unlock(&LOCK_thread_count); mysql_mutex_unlock(&LOCK_thread_count);
/* /*
...@@ -241,13 +236,8 @@ event_scheduler_thread(void *arg) ...@@ -241,13 +236,8 @@ event_scheduler_thread(void *arg)
my_free(arg); my_free(arg);
if (!res) if (!res)
scheduler->run(thd); scheduler->run(thd);
else
{
thd->proc_info= "Clearing";
net_end(&thd->net);
delete thd;
}
deinit_event_thread(thd);
DBUG_LEAVE; // Against gcc warnings DBUG_LEAVE; // Against gcc warnings
my_thread_end(); my_thread_end();
return 0; return 0;
...@@ -308,6 +298,7 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event) ...@@ -308,6 +298,7 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
DBUG_ENTER("Event_worker_thread::run"); DBUG_ENTER("Event_worker_thread::run");
DBUG_PRINT("info", ("Time is %ld, THD: 0x%lx", (long) my_time(0), (long) thd)); DBUG_PRINT("info", ("Time is %ld, THD: 0x%lx", (long) my_time(0), (long) thd));
inc_thread_running();
if (res) if (res)
goto end; goto end;
...@@ -334,6 +325,7 @@ end: ...@@ -334,6 +325,7 @@ end:
event->name.str)); event->name.str));
delete event; delete event;
dec_thread_running();
deinit_event_thread(thd); deinit_event_thread(thd);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -432,13 +424,9 @@ Event_scheduler::start(int *err_no) ...@@ -432,13 +424,9 @@ Event_scheduler::start(int *err_no)
" Can not create thread for event scheduler (errno=%d)", " Can not create thread for event scheduler (errno=%d)",
*err_no); *err_no);
new_thd->proc_info= "Clearing";
DBUG_ASSERT(new_thd->net.buff != 0);
net_end(&new_thd->net);
state= INITIALIZED; state= INITIALIZED;
scheduler_thd= NULL; scheduler_thd= NULL;
delete new_thd; deinit_event_thread(new_thd);
delete scheduler_param_value; delete scheduler_param_value;
ret= true; ret= true;
...@@ -505,7 +493,6 @@ Event_scheduler::run(THD *thd) ...@@ -505,7 +493,6 @@ Event_scheduler::run(THD *thd)
} }
LOCK_DATA(); LOCK_DATA();
deinit_event_thread(thd);
scheduler_thd= NULL; scheduler_thd= NULL;
state= INITIALIZED; state= INITIALIZED;
DBUG_PRINT("info", ("Broadcasting COND_state back to the stoppers")); DBUG_PRINT("info", ("Broadcasting COND_state back to the stoppers"));
...@@ -564,10 +551,7 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name) ...@@ -564,10 +551,7 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name)
sql_print_error("Event_scheduler::execute_top: Can not create event worker" sql_print_error("Event_scheduler::execute_top: Can not create event worker"
" thread (errno=%d). Stopping event scheduler", res); " thread (errno=%d). Stopping event scheduler", res);
new_thd->proc_info= "Clearing"; deinit_event_thread(new_thd);
DBUG_ASSERT(new_thd->net.buff != 0);
net_end(&new_thd->net);
goto error; goto error;
} }
...@@ -579,9 +563,6 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name) ...@@ -579,9 +563,6 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name)
error: error:
DBUG_PRINT("error", ("Event_scheduler::execute_top() res: %d", res)); DBUG_PRINT("error", ("Event_scheduler::execute_top() res: %d", res));
if (new_thd)
delete new_thd;
delete event_name; delete event_name;
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment