From e2ac8c07bdd2e58f5f7b4919a76a0d1881f3ed5e Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Tue, 23 Jun 2009 12:10:04 +0300 Subject: [PATCH] Bug #38240 Crash in safe_mutex_lock () thr_mutex.c line 97 on rotate_relay_log The reason for the crash was rotate_relay_log (mi=0x0) did not verify the passed value of active_mi. There are more cases where active_mi is supposed to be non-zero e.g change_master(), stop_slave(), and it's reasonable to protect from a similar crash all of them with common fixes. Fixed with spliting end_slave() in slave threads release and slave data clean-up parts (a new close_active_mi()). The new function is invoked at the very end of close_connections() so that all users of active_mi are proven to have left. sql/mysqld.cc: added the 2nd part (data) of the slave's clean up. sql/slave.cc: end_slave() is split in two part to release the slave threads and the remained resources separately. The new close_active_mi() should be called after all possible users ofactive_mi has left, i.e at the very end of close_connections(). sql/slave.h: interface to the new end_active_mi() function is added. --- sql/mysqld.cc | 1 + sql/slave.cc | 25 +++++++++++++++++++++---- sql/slave.h | 3 ++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1d18226ab45..f7ee7b025f9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -983,6 +983,7 @@ static void close_connections(void) } (void) pthread_mutex_unlock(&LOCK_thread_count); + close_active_mi(); DBUG_PRINT("quit",("close_connections thread")); DBUG_VOID_RETURN; } diff --git a/sql/slave.cc b/sql/slave.cc index 043b0e3fed5..5570a07c02d 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -668,7 +668,7 @@ static int end_slave_on_walk(Master_info* mi, uchar* /*unused*/) /* - Free all resources used by slave + Release slave threads at time of executing shutdown. SYNOPSIS end_slave() @@ -694,14 +694,31 @@ void end_slave() once multi-master code is ready. */ terminate_slave_threads(active_mi,SLAVE_FORCE_ALL); - end_master_info(active_mi); - delete active_mi; - active_mi= 0; } pthread_mutex_unlock(&LOCK_active_mi); DBUG_VOID_RETURN; } +/** + Free all resources used by slave threads at time of executing shutdown. + The routine must be called after all possible users of @c active_mi + have left. + + SYNOPSIS + close_active_mi() + +*/ +void close_active_mi() +{ + pthread_mutex_lock(&LOCK_active_mi); + if (active_mi) + { + end_master_info(active_mi); + delete active_mi; + active_mi= 0; + } + pthread_mutex_unlock(&LOCK_active_mi); +} static bool io_slave_killed(THD* thd, Master_info* mi) { diff --git a/sql/slave.h b/sql/slave.h index abd63315e62..160418955b5 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -174,7 +174,8 @@ const char *print_slave_db_safe(const char *db); int check_expected_error(THD* thd, Relay_log_info const *rli, int error_code); void skip_load_data_infile(NET* net); -void end_slave(); /* clean up */ +void end_slave(); /* release slave threads */ +void close_active_mi(); /* clean up slave threads data */ void clear_until_condition(Relay_log_info* rli); void clear_slave_error(Relay_log_info* rli); void end_relay_log_info(Relay_log_info* rli);