[PATCH] MDEV-29744: 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. Note that when this is merged to 11.4, similar unlock/lock of LOCK_global_system_variables must be added in update_binlog_space_limit() as is done in binlog_checksum_update() and fix_max_binlog_size(), as this is a new function added in 11.4 that also needs the same fix. Tests will fail with wrong mutex order until this is done. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org> fixup_locking_order Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org> --- sql/log.cc | 5 +++++ sql/sys_vars.cc | 2 ++ 2 files changed, 7 insertions(+) diff --git a/sql/log.cc b/sql/log.cc index 512be2e2a6d..ecb177a34fb 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3595,6 +3595,9 @@ 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_record_order(&LOCK_log, &LOCK_global_system_variables); } @@ -11753,6 +11756,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 +11775,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.5
participants (1)
-
Kristian Nielsen