[PATCH] MDEV-35197: Fix incorrect locking order of LOCK_log/LOCK_commit_ordered and LOCK_global_system_variables
The LOCK_global_system_variables must not be held when taking mutexes such as LOCK_commit_ordered and LOCK_log, as this causes inconsistent mutex locking order that can theoretically cause the server to deadlock. To avoid this, temporarily release LOCK_global_system_variables in two system variable update functions, like it is done in many other places. Enforce the correct locking order at server startup, to more easily catch (in debug builds) any remaining wrong orders that may be hidden elsewhere in the code. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org> --- sql/log.cc | 8 ++++++++ sql/sys_vars.cc | 2 ++ 2 files changed, 10 insertions(+) diff --git a/sql/log.cc b/sql/log.cc index 512be2e2a6d..70fe33f9272 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3595,6 +3595,12 @@ void MYSQL_BIN_LOG::init_pthread_objects() mysql_mutex_init(m_key_LOCK_binlog_end_pos, &LOCK_binlog_end_pos, MY_MUTEX_INIT_SLOW); + + /* Fix correct mutex order to catch violations quicker (MDEV-35197). */ + mysql_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_log); } @@ -11753,6 +11759,7 @@ binlog_checksum_update(MYSQL_THD thd, struct st_mysql_sys_var *var, bool check_purge= false; ulong UNINIT_VAR(prev_binlog_id); + mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(mysql_bin_log.get_log_lock()); if(mysql_bin_log.is_open()) { @@ -11771,6 +11778,7 @@ binlog_checksum_update(MYSQL_THD thd, struct st_mysql_sys_var *var, mysql_mutex_unlock(mysql_bin_log.get_log_lock()); if (check_purge) mysql_bin_log.checkpoint_and_purge(prev_binlog_id); + mysql_mutex_lock(&LOCK_global_system_variables); } diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index cb35386f883..115bbdf499b 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1660,7 +1660,9 @@ Sys_max_binlog_stmt_cache_size( static bool fix_max_binlog_size(sys_var *self, THD *thd, enum_var_type type) { + mysql_mutex_unlock(&LOCK_global_system_variables); mysql_bin_log.set_max_size(max_binlog_size); + mysql_mutex_lock(&LOCK_global_system_variables); return false; } static Sys_var_on_access_global<Sys_var_ulong, -- 2.39.2
participants (1)
-
Kristian Nielsen