diff options
author | Igor Babaev <igor@askmonty.org> | 2012-08-29 18:50:38 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-08-29 18:50:38 -0700 |
commit | 98f239a8494104743b4a7f2df5b8d7f310975689 (patch) | |
tree | 4beee747e184ab6b7d873d936e244397e4f8b49d /sql/sys_vars.cc | |
parent | d0ad93fbc7eca575364e46f67c4613efb0807047 (diff) | |
parent | b45c551ee32d0d5260f4958abf93efab1a4614a2 (diff) | |
download | mariadb-git-98f239a8494104743b4a7f2df5b8d7f310975689.tar.gz |
Merge 5.5->5.5-mwl248.
Diffstat (limited to 'sql/sys_vars.cc')
-rw-r--r-- | sql/sys_vars.cc | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 47dc8b3addf..01505525d7e 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -47,6 +47,7 @@ #include "sql_base.h" // close_cached_tables #include <myisam.h> #include "log_slow.h" +#include "debug_sync.h" // DEBUG_SYNC #include "log_event.h" #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE @@ -3256,6 +3257,13 @@ bool Sys_var_rpl_filter::do_check(THD *thd, set_var *var) { bool status; + /* + We must not be holding LOCK_global_system_variables here, otherwise we can + deadlock with THD::init() which is invoked from within the slave threads + with opposite locking order. + */ + mysql_mutex_assert_not_owner(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_active_mi); mysql_mutex_lock(&active_mi->rli.run_lock); @@ -3272,22 +3280,43 @@ bool Sys_var_rpl_filter::do_check(THD *thd, set_var *var) return status; } -bool Sys_var_rpl_filter::global_update(THD *thd, set_var *var) +void Sys_var_rpl_filter::lock(void) { - bool slave_running, status= false; + /* + Starting a slave thread causes the new thread to attempt to + acquire LOCK_global_system_variables (in THD::init) while + LOCK_active_mi is being held by the thread that initiated + the process. In order to not violate the lock order, unlock + LOCK_global_system_variables before grabbing LOCK_active_mi. + */ + mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); mysql_mutex_lock(&active_mi->rli.run_lock); +} - if (! (slave_running= active_mi->rli.slave_running)) - status= set_filter_value(var->save_result.string_value.str); - +void Sys_var_rpl_filter::unlock(void) +{ mysql_mutex_unlock(&active_mi->rli.run_lock); mysql_mutex_unlock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_global_system_variables); +} + +bool Sys_var_rpl_filter::global_update(THD *thd, set_var *var) +{ + bool slave_running, status= false; + + lock(); + + if (! (slave_running= active_mi->rli.slave_running)) + status= set_filter_value(var->save_result.string_value.str); + if (slave_running) my_error(ER_SLAVE_MUST_STOP, MYF(0)); + unlock(); + return slave_running || status; } @@ -3326,8 +3355,7 @@ uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd, LEX_STRING *base) tmp.length(0); - mysql_mutex_lock(&LOCK_active_mi); - mysql_mutex_lock(&active_mi->rli.run_lock); + lock(); switch (opt_id) { case OPT_REPLICATE_DO_DB: @@ -3350,8 +3378,7 @@ uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd, LEX_STRING *base) break; } - mysql_mutex_unlock(&active_mi->rli.run_lock); - mysql_mutex_unlock(&LOCK_active_mi); + unlock(); return (uchar *) thd->strmake(tmp.ptr(), tmp.length()); } @@ -3404,6 +3431,9 @@ static Sys_var_charptr Sys_slave_load_tmpdir( static bool fix_slave_net_timeout(sys_var *self, THD *thd, enum_var_type type) { + DEBUG_SYNC(thd, "fix_slave_net_timeout"); + + mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); DBUG_PRINT("info", ("slave_net_timeout=%u mi->heartbeat_period=%.3f", slave_net_timeout, @@ -3413,6 +3443,7 @@ static bool fix_slave_net_timeout(sys_var *self, THD *thd, enum_var_type type) ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX, ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX)); mysql_mutex_unlock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_global_system_variables); return false; } static Sys_var_uint Sys_slave_net_timeout( @@ -3439,6 +3470,7 @@ static bool check_slave_skip_counter(sys_var *self, THD *thd, set_var *var) } static bool fix_slave_skip_counter(sys_var *self, THD *thd, enum_var_type type) { + mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); mysql_mutex_lock(&active_mi->rli.run_lock); /* @@ -3454,6 +3486,7 @@ static bool fix_slave_skip_counter(sys_var *self, THD *thd, enum_var_type type) } mysql_mutex_unlock(&active_mi->rli.run_lock); mysql_mutex_unlock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_global_system_variables); return 0; } static Sys_var_uint Sys_slave_skip_counter( |