Remove a race between Event Scheduler shutdown and SHOW PROCESSLIST.

This will hopefully fix events.test failure on vmware-win32, 
where scheduling is very primitive.


mysql-test/t/events_scheduling.test:
  This test case has no races now and can be enabled under valgrind.
sql/event_scheduler.cc:
  Make Event Scheduler thread shutdown more synchronous: report
  successful shutdown only after having removed the scheduler
  thread from the global list of threads.
  This ensures that after the scheduler has been stopped, its
  thread is not present in SHOW PROCESSLIST output.
This commit is contained in:
unknown 2007-04-06 19:44:14 +04:00
parent 306be7fee9
commit c557623a68
2 changed files with 7 additions and 18 deletions

View file

@ -1,6 +1,5 @@
# Can't test with embedded server that doesn't support grants # Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc -- source include/not_embedded.inc
-- source include/not_valgrind.inc
CREATE DATABASE IF NOT EXISTS events_test; CREATE DATABASE IF NOT EXISTS events_test;
USE events_test; USE events_test;

View file

@ -154,8 +154,6 @@ deinit_event_thread(THD *thd)
thread_running--; thread_running--;
delete thd; delete thd;
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
my_thread_end();
} }
@ -231,8 +229,7 @@ event_scheduler_thread(void *arg)
if (!res) if (!res)
scheduler->run(thd); scheduler->run(thd);
deinit_event_thread(thd); my_thread_end();
pthread_exit(0);
DBUG_RETURN(0); // Against gcc warnings DBUG_RETURN(0); // Against gcc warnings
} }
@ -260,6 +257,7 @@ event_worker_thread(void *arg)
Event_worker_thread worker_thread; Event_worker_thread worker_thread;
worker_thread.run(thd, event); worker_thread.run(thd, event);
my_thread_end();
return 0; // Can't return anything here return 0; // Can't return anything here
} }
@ -494,12 +492,14 @@ Event_scheduler::run(THD *thd)
} }
DBUG_PRINT("info", ("state=%s", scheduler_states_names[state].str)); DBUG_PRINT("info", ("state=%s", scheduler_states_names[state].str));
} }
LOCK_DATA(); LOCK_DATA();
DBUG_PRINT("info", ("Signalling back to the stopper COND_state")); deinit_event_thread(thd);
scheduler_thd= NULL;
state= INITIALIZED; state= INITIALIZED;
DBUG_PRINT("info", ("Signalling back to the stopper COND_state"));
pthread_cond_signal(&COND_state); pthread_cond_signal(&COND_state);
UNLOCK_DATA(); UNLOCK_DATA();
sql_print_information("Event Scheduler: Stopped");
DBUG_RETURN(res); DBUG_RETURN(res);
} }
@ -651,17 +651,7 @@ Event_scheduler::stop()
COND_STATE_WAIT(thd, NULL, "Waiting scheduler to stop"); COND_STATE_WAIT(thd, NULL, "Waiting scheduler to stop");
} while (state == STOPPING); } while (state == STOPPING);
DBUG_PRINT("info", ("Scheduler thread has cleaned up. Set state to INIT")); DBUG_PRINT("info", ("Scheduler thread has cleaned up. Set state to INIT"));
/* sql_print_information("Event Scheduler: Stopped");
The rationale behind setting it to NULL here but not destructing it
beforehand is because the THD will be deinited in event_scheduler_thread().
It's more clear when the post_init and the deinit is done in one function.
Here we just mark that the scheduler doesn't have a THD anymore. Though for
milliseconds the old thread could exist we can't use it anymore. When we
unlock the mutex in this function a little later the state will be
INITIALIZED. Therefore, a connection thread could enter the critical section
and will create a new THD object.
*/
scheduler_thd= NULL;
end: end:
UNLOCK_DATA(); UNLOCK_DATA();
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);