summaryrefslogtreecommitdiff
path: root/sql/wsrep_var.cc
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2021-02-12 17:31:25 +0100
committerSergei Golubchik <serg@mariadb.org>2021-02-14 23:18:42 +0100
commit26965387230a9b13fb716344477d108bb87dea98 (patch)
treead6c110d3d82f073554489610265b56f758efb73 /sql/wsrep_var.cc
parentb91e77cff3fb5fbb32ebb061ed342469b434c4e8 (diff)
downloadmariadb-git-26965387230a9b13fb716344477d108bb87dea98.tar.gz
updating @@wsrep_cluster_address deadlocks
wsrep_cluster_address_update() causes LOCK_wsrep_slave_threads to be locked under LOCK_wsrep_cluster_config, while normally the order should be the opposite. Fix: don't protect @@wsrep_cluster_address value with the LOCK_wsrep_cluster_config, LOCK_global_system_variables is enough. Only protect wsrep reinitialization with the LOCK_wsrep_cluster_config. And make it use a local copy of the global @@wsrep_cluster_address. Also, introduce a helper function that checks whether wsrep_cluster_address is set and also asserts that it can be safely read by the caller.
Diffstat (limited to 'sql/wsrep_var.cc')
-rw-r--r--sql/wsrep_var.cc28
1 files changed, 15 insertions, 13 deletions
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index 239daadc4f6..35f14532e85 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -554,30 +554,31 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
/* stop replication is heavy operation, and includes closing all client
connections. Closing clients may need to get LOCK_global_system_variables
at least in MariaDB.
-
- Note: releasing LOCK_global_system_variables may cause race condition, if
- there can be several concurrent clients changing wsrep_provider
*/
+ char *tmp= my_strdup(wsrep_cluster_address, MYF(MY_WME));
WSREP_DEBUG("wsrep_cluster_address_update: %s", wsrep_cluster_address);
mysql_mutex_unlock(&LOCK_global_system_variables);
+
+ mysql_mutex_lock(&LOCK_wsrep_cluster_config);
wsrep_stop_replication(thd);
- if (wsrep_start_replication())
+ if (*tmp && wsrep_start_replication(tmp))
{
wsrep_create_rollbacker();
WSREP_DEBUG("Cluster address update creating %ld applier threads running %lu",
wsrep_slave_threads, wsrep_running_applier_threads);
wsrep_create_appliers(wsrep_slave_threads);
}
- /* locking order to be enforced is:
- 1. LOCK_global_system_variables
- 2. LOCK_wsrep_cluster_config
- => have to juggle mutexes to comply with this
- */
-
mysql_mutex_unlock(&LOCK_wsrep_cluster_config);
+
mysql_mutex_lock(&LOCK_global_system_variables);
- mysql_mutex_lock(&LOCK_wsrep_cluster_config);
+ if (strcmp(tmp, wsrep_cluster_address))
+ {
+ my_free((void*)wsrep_cluster_address);
+ wsrep_cluster_address= tmp;
+ }
+ else
+ my_free(tmp);
return false;
}
@@ -674,11 +675,12 @@ static void wsrep_slave_count_change_update ()
bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type)
{
- mysql_mutex_unlock(&LOCK_wsrep_cluster_config);
+ if (!wsrep_cluster_address_exists())
+ return false;
+
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_wsrep_slave_threads);
mysql_mutex_lock(&LOCK_global_system_variables);
- mysql_mutex_lock(&LOCK_wsrep_cluster_config);
bool res= false;
wsrep_slave_count_change_update();