summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormkaruza <mario.karuza@galeracluster.com>2020-06-02 09:18:59 +0200
committerJan Lindström <jan.lindstrom@mariadb.com>2020-07-24 12:05:39 +0300
commit4b4372af6a6e2e3c37220487bdb671054357698e (patch)
treea26bf55738600e42175af1d9de08593885b7f2bc
parent6b8b7b1e8cd876f798df10015c9853da8adb00f8 (diff)
downloadmariadb-git-4b4372af6a6e2e3c37220487bdb671054357698e.tar.gz
MDEV-22458: Server with WSREP hangs after INSERT, wrong usage of mutex 'LOCK_thd_data' and 'share->intern_lock' / 'lock->mutex'
Add `find_thread_by_id_with_thd_data_lock` which will be used only when killing thread. This version needs to take `thd->LOCK_thd_data` lock.
-rw-r--r--mysql-test/suite/galera/r/MDEV-22458.result10
-rw-r--r--mysql-test/suite/galera/t/MDEV-22458.test21
-rw-r--r--sql/sql_parse.cc28
3 files changed, 57 insertions, 2 deletions
diff --git a/mysql-test/suite/galera/r/MDEV-22458.result b/mysql-test/suite/galera/r/MDEV-22458.result
new file mode 100644
index 00000000000..d1f9d94bd1c
--- /dev/null
+++ b/mysql-test/suite/galera/r/MDEV-22458.result
@@ -0,0 +1,10 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (a INT);
+connect con1,localhost,root,,test;
+INSERT INTO t1 VALUES (1),(2),(3),(4);
+SHOW EXPLAIN FOR $con1;
+ERROR HY000: Target is not running an EXPLAINable command
+connection con1;
+INSERT INTO t1 VALUES (5),(6),(7),(8);
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/MDEV-22458.test b/mysql-test/suite/galera/t/MDEV-22458.test
new file mode 100644
index 00000000000..8f9ba1bb107
--- /dev/null
+++ b/mysql-test/suite/galera/t/MDEV-22458.test
@@ -0,0 +1,21 @@
+# MDEV-22458
+#
+# When running SHOW command, thread lock `LOCK_thd_data` should not be taken.
+# Lock will be taken only when we are killing thread
+#
+
+--source include/galera_cluster.inc
+CREATE TABLE t1 (a INT);
+
+--connect (con1,localhost,root,,test)
+--let $con1 = `SELECT CONNECTION_ID()`
+
+INSERT INTO t1 VALUES (1),(2),(3),(4);
+
+--error ER_TARGET_NOT_EXPLAINABLE
+EVALP SHOW EXPLAIN FOR $con1;
+
+--connection con1
+INSERT INTO t1 VALUES (5),(6),(7),(8);
+
+DROP TABLE t1;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 3c5c52e2aa1..4596915b096 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -9019,7 +9019,6 @@ my_bool find_thread_callback(THD *thd, find_thread_callback_arg *arg)
if (thd->get_command() != COM_DAEMON &&
arg->id == (arg->query_id ? thd->query_id : (longlong) thd->thread_id))
{
- if (WSREP(thd)) mysql_mutex_lock(&thd->LOCK_thd_data);
mysql_mutex_lock(&thd->LOCK_thd_kill); // Lock from delete
arg->thd= thd;
return 1;
@@ -9035,6 +9034,26 @@ THD *find_thread_by_id(longlong id, bool query_id)
return arg.thd;
}
+#ifdef WITH_WSREP
+my_bool find_thread_with_thd_data_lock_callback(THD *thd, find_thread_callback_arg *arg)
+{
+ if (thd->get_command() != COM_DAEMON &&
+ arg->id == (arg->query_id ? thd->query_id : (longlong) thd->thread_id))
+ {
+ if (WSREP(thd)) mysql_mutex_lock(&thd->LOCK_thd_data);
+ mysql_mutex_lock(&thd->LOCK_thd_kill); // Lock from delete
+ arg->thd= thd;
+ return 1;
+ }
+ return 0;
+}
+THD *find_thread_by_id_with_thd_data_lock(longlong id, bool query_id)
+{
+ find_thread_callback_arg arg(id, query_id);
+ server_threads.iterate(find_thread_with_thd_data_lock_callback, &arg);
+ return arg.thd;
+}
+#endif
/**
kill one thread.
@@ -9052,7 +9071,11 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
uint error= (type == KILL_TYPE_QUERY ? ER_NO_SUCH_QUERY : ER_NO_SUCH_THREAD);
DBUG_ENTER("kill_one_thread");
DBUG_PRINT("enter", ("id: %lld signal: %u", id, (uint) kill_signal));
+#ifdef WITH_WSREP
+ if (id && (tmp= find_thread_by_id_with_thd_data_lock(id, type == KILL_TYPE_QUERY)))
+#else
if (id && (tmp= find_thread_by_id(id, type == KILL_TYPE_QUERY)))
+#endif
{
/*
If we're SUPER, we can KILL anything, including system-threads.
@@ -9106,8 +9129,9 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
else
error= (type == KILL_TYPE_QUERY ? ER_KILL_QUERY_DENIED_ERROR :
ER_KILL_DENIED_ERROR);
-
+#ifdef WITH_WSREP
if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_thd_data);
+#endif
mysql_mutex_unlock(&tmp->LOCK_thd_kill);
}
DBUG_PRINT("exit", ("%d", error));