summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2020-09-18 17:35:08 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2020-09-18 17:35:08 +0200
commitdec45aca77ee23557c59411fa9abf037e5343739 (patch)
tree1a55e58684ed202d76c24ee59cc86504294a2cbe
parent46fab5b32a84a1ffd181dd16b5cd63958faf010b (diff)
downloadmariadb-git-bb-10.6-MDEV-16440-2.tar.gz
MDEV-23752 SHOW EXPLAIN FOR thd waits for sleepbb-10.6-MDEV-16440-2
my_apc awake thread after request.
-rw-r--r--mysql-test/main/processlist_notembedded.result13
-rw-r--r--mysql-test/main/processlist_notembedded.test18
-rw-r--r--sql/event_scheduler.cc4
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/my_apc.cc8
-rw-r--r--sql/my_apc.h3
-rw-r--r--sql/rpl_parallel.cc2
-rw-r--r--sql/service_wsrep.cc4
-rw-r--r--sql/slave.cc7
-rw-r--r--sql/sql_class.cc21
-rw-r--r--sql/sql_class.h13
-rw-r--r--sql/sql_parse.cc7
-rw-r--r--sql/sql_repl.cc2
-rw-r--r--sql/sql_show.cc3
-rw-r--r--sql/wsrep_mysqld.cc7
-rw-r--r--unittest/sql/my_apc-t.cc2
16 files changed, 87 insertions, 29 deletions
diff --git a/mysql-test/main/processlist_notembedded.result b/mysql-test/main/processlist_notembedded.result
index b622fdf32b9..ab4d3f4d265 100644
--- a/mysql-test/main/processlist_notembedded.result
+++ b/mysql-test/main/processlist_notembedded.result
@@ -14,3 +14,16 @@ disconnect con1;
connection default;
SET DEBUG_SYNC = 'RESET';
End of 5.5 tests
+#
+# MDEV-23752: SHOW EXPLAIN FOR thd waits for sleep
+#
+connect con1,localhost,root,,;
+select sleep(100000);;
+connection default;
+SHOW EXPLAIN FOR con_id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select sleep(100000)
+KILL QUERY con_id;
+# End of 10.6 tests
diff --git a/mysql-test/main/processlist_notembedded.test b/mysql-test/main/processlist_notembedded.test
index 6f269a816fc..8a9ac1bacc5 100644
--- a/mysql-test/main/processlist_notembedded.test
+++ b/mysql-test/main/processlist_notembedded.test
@@ -40,3 +40,21 @@ SET DEBUG_SYNC = 'RESET';
source include/wait_until_count_sessions.inc;
--echo End of 5.5 tests
+
+--echo #
+--echo # MDEV-23752: SHOW EXPLAIN FOR thd waits for sleep
+--echo #
+
+--connect (con1,localhost,root,,)
+--let $con_id = `SELECT CONNECTION_ID()`
+--send select sleep(100000);
+
+--connection default
+
+--replace_result $con_id con_id
+eval SHOW EXPLAIN FOR $con_id;
+
+--replace_result $con_id con_id
+eval KILL QUERY $con_id;
+
+--echo # End of 10.6 tests
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index 78802a5e109..86075485865 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -668,7 +668,7 @@ Event_scheduler::stop()
sql_print_information("Event Scheduler: Killing the scheduler thread, "
"thread id %lu",
(ulong) scheduler_thd->thread_id);
- scheduler_thd->awake(KILL_CONNECTION);
+ scheduler_thd->kill_me_pls(KILL_CONNECTION);
/* thd could be 0x0, when shutting down */
sql_print_information("Event Scheduler: "
@@ -676,7 +676,7 @@ Event_scheduler::stop()
/*
Wait only 2 seconds, as there is a small chance the thread missed the
- above awake() call and we may have to do it again
+ above kill_me_pls() call and we may have to do it again
*/
struct timespec top_time;
set_timespec(top_time, 2);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 8a75d2c9946..e0137d08dfb 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -4017,6 +4017,8 @@ int Interruptible_wait::wait(mysql_cond_t *cond, mysql_mutex_t *mutex)
timeout= m_abs_timeout;
error= mysql_cond_timedwait(cond, mutex, &timeout);
+ if (m_thd->check_killed(TRUE))
+ break;
if (error == ETIMEDOUT || error == ETIME)
{
/* Return error if timed out or connection is broken. */
diff --git a/sql/my_apc.cc b/sql/my_apc.cc
index e0feabab8e2..13575c994f4 100644
--- a/sql/my_apc.cc
+++ b/sql/my_apc.cc
@@ -123,7 +123,7 @@ void init_show_explain_psi_keys(void)
timeout occurred)
*/
-bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call,
+bool Apc_target::make_apc_call(THD *thd, THD *caller_thd, Apc_call *call,
int timeout_sec, bool *timed_out)
{
bool res= TRUE;
@@ -139,7 +139,11 @@ bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call,
NULL);
enqueue_request(&apc_request);
apc_request.what="enqueued by make_apc_call";
-
+
+#ifndef MY_APC_STANDALONE
+ thd->awake_me();
+#endif //MY_APC_STANDALONE
+
struct timespec abstime;
const int timeout= timeout_sec;
set_timespec(abstime, timeout);
diff --git a/sql/my_apc.h b/sql/my_apc.h
index cc98e36bbe4..34f507dcd01 100644
--- a/sql/my_apc.h
+++ b/sql/my_apc.h
@@ -96,7 +96,8 @@ public:
};
/* Make a call in the target thread (see function definition for details) */
- bool make_apc_call(THD *caller_thd, Apc_call *call, int timeout_sec, bool *timed_out);
+ bool make_apc_call(THD *thd, THD *caller_thd, Apc_call *call,
+ int timeout_sec, bool *timed_out);
#ifndef DBUG_OFF
int n_calls_processed; /* Number of calls served by this target */
diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc
index 72347d93ad1..1f10c945d12 100644
--- a/sql/rpl_parallel.cc
+++ b/sql/rpl_parallel.cc
@@ -2203,7 +2203,7 @@ rpl_parallel_entry::choose_thread(rpl_group_info *rgi, bool *did_enter_cond,
/*
We need to do the debug_sync before ENTER_COND().
Because debug_sync changes the thd->mysys_var->current_mutex,
- and this can cause THD::awake to use the wrong mutex.
+ and this can cause THD::kill_me_pls to use the wrong mutex.
*/
DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max",
{
diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc
index f61db1e80e8..cce4614c00f 100644
--- a/sql/service_wsrep.cc
+++ b/sql/service_wsrep.cc
@@ -231,7 +231,7 @@ extern "C" my_bool wsrep_thd_bf_abort(THD *bf_thd, THD *victim_thd,
mysql_mutex_lock(&victim_thd->LOCK_thd_kill);
victim_thd->wsrep_aborter= bf_thd->thread_id;
- victim_thd->awake_no_mutex(KILL_QUERY);
+ victim_thd->kill_me_pls_no_mutex(KILL_QUERY);
mysql_mutex_unlock(&victim_thd->LOCK_thd_kill);
mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
} else {
@@ -372,4 +372,4 @@ extern "C" bool wsrep_thd_set_wsrep_aborter(THD *bf_thd, THD *victim_thd)
}
victim_thd->wsrep_aborter = bf_thd->thread_id;
return false;
-} \ No newline at end of file
+}
diff --git a/sql/slave.cc b/sql/slave.cc
index cc50638ae5b..ed05fee5fba 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -535,7 +535,7 @@ handle_slave_background(void *arg __attribute__((unused)))
THD *to_kill= p->to_kill;
kill_list= p->next;
- to_kill->awake(KILL_CONNECTION);
+ to_kill->kill_me_pls(KILL_CONNECTION);
mysql_mutex_lock(&to_kill->LOCK_wakeup_ready);
to_kill->rgi_slave->killed_for_retry=
rpl_group_info::RETRY_KILL_KILLED;
@@ -1216,7 +1216,7 @@ terminate_slave_thread(THD *thd,
DBUG_PRINT("loop", ("killing slave thread"));
#ifdef WITH_WSREP
- /* awake_no_mutex() requires LOCK_thd_data to be locked if wsrep
+ /* kill_me_pls_no_mutex() requires LOCK_thd_data to be locked if wsrep
is enabled */
if (WSREP(thd)) mysql_mutex_lock(&thd->LOCK_thd_data);
#endif /* WITH_WSREP */
@@ -1230,7 +1230,8 @@ terminate_slave_thread(THD *thd,
int err __attribute__((unused))= pthread_kill(thd->real_id, thr_client_alarm);
DBUG_ASSERT(err != EINVAL);
#endif
- thd->awake_no_mutex(NOT_KILLED);
+ thd->kill_me_pls_no_mutex(NOT_KILLED);
+
mysql_mutex_unlock(&thd->LOCK_thd_kill);
#ifdef WITH_WSREP
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ac952fffae8..68159c21f32 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -633,7 +633,7 @@ extern "C" void thd_kill_timeout(THD* thd)
{
thd->status_var.max_statement_time_exceeded++;
/* Kill queries that can't cause data corruptions */
- thd->awake(KILL_TIMEOUT);
+ thd->kill_me_pls(KILL_TIMEOUT);
}
THD::THD(my_thread_id id, bool is_wsrep_applier)
@@ -1887,9 +1887,9 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
NOT_KILLED is used to awake a thread for a slave
*/
-void THD::awake_no_mutex(killed_state state_to_set)
+void THD::kill_me_pls_no_mutex(killed_state state_to_set)
{
- DBUG_ENTER("THD::awake");
+ DBUG_ENTER("THD::kill_me_pls_no_mutex");
DBUG_PRINT("enter", ("this: %p current_thd: %p state: %d",
this, current_thd, (int) state_to_set));
THD_CHECK_SENTRY(this);
@@ -1930,9 +1930,20 @@ void THD::awake_no_mutex(killed_state state_to_set)
state_to_set != NOT_KILLED))
ha_kill_query(this, thd_kill_level(this));
+
+ awake_me();
+ DBUG_VOID_RETURN;
+}
+
+void THD::awake_me()
+{
+ DBUG_ENTER("THD::awake_me");
+ mysql_mutex_assert_owner(&LOCK_thd_kill);
/* Broadcast a condition to kick the target if it is waiting on it. */
if (mysys_var)
{
+ DBUG_PRINT("enter", ("this: %p current_thd: %p mysys_var",
+ this, current_thd));
mysql_mutex_lock(&mysys_var->mutex);
if (!system_thread) // Don't abort locks
mysys_var->abort=1;
@@ -2145,7 +2156,7 @@ void THD::reset_killed()
{
/*
Resetting killed has to be done under a mutex to ensure
- its not done during an awake() call.
+ its not done during an kill_me_pls() call.
*/
DBUG_ENTER("reset_killed");
if (killed != NOT_KILLED)
@@ -4973,7 +4984,7 @@ extern "C" size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen)
{
size_t len= 0;
/* InnoDB invokes this function while holding internal mutexes.
- THD::awake() will hold LOCK_thd_data while invoking an InnoDB
+ THD::kill_me_pls() will hold LOCK_thd_data while invoking an InnoDB
function that would acquire the internal mutex. Because this
function is a non-essential part of information_schema view output,
we will break the deadlock by avoiding a mutex wait here
diff --git a/sql/sql_class.h b/sql/sql_class.h
index b0f68aa8fab..e3e3827e32b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3171,7 +3171,7 @@ public:
/*
If checking this in conjunction with a wait condition, please
include a check after enter_cond() if you want to avoid a race
- condition. For details see the implementation of awake(),
+ condition. For details see the implementation of kill_me_pls(),
especially the "broadcast" part.
*/
killed_state volatile killed;
@@ -3436,8 +3436,8 @@ public:
}
void close_active_vio();
#endif
- void awake_no_mutex(killed_state state_to_set);
- void awake(killed_state state_to_set)
+ void kill_me_pls_no_mutex(killed_state state_to_set);
+ void kill_me_pls(killed_state state_to_set)
{
bool wsrep_on_local= WSREP_NNULL(this);
/*
@@ -3447,7 +3447,7 @@ public:
if (wsrep_on_local)
mysql_mutex_lock(&LOCK_thd_data);
mysql_mutex_lock(&LOCK_thd_kill);
- awake_no_mutex(state_to_set);
+ kill_me_pls_no_mutex(state_to_set);
mysql_mutex_unlock(&LOCK_thd_kill);
if (wsrep_on_local)
mysql_mutex_unlock(&LOCK_thd_data);
@@ -3507,7 +3507,7 @@ public:
Putting the mutex unlock in thd->exit_cond() ensures that
mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
locked (if that would not be the case, you'll get a deadlock if someone
- does a THD::awake() on you).
+ does a THD::kill_me_pls() on you).
*/
mysql_mutex_unlock(mysys_var->current_mutex);
mysql_mutex_lock(&mysys_var->mutex);
@@ -4957,6 +4957,9 @@ private:
}
public:
+
+ void awake_me();
+
#ifdef HAVE_REPLICATION
/*
If we do a purge of binary logs, log index info of the threads
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 8c95aa0a760..85b10d8cf88 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7649,7 +7649,7 @@ static bool wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
/*
Convert all ER_QUERY_INTERRUPTED errors to ER_LOCK_DEADLOCK
if the transaction was BF aborted. This can happen when the
- transaction is being BF aborted via thd->awake() while it is
+ transaction is being BF aborted via thd->kill_me_pls() while it is
still executing.
Note that this must be done before wsrep_after_statement() call
@@ -9047,6 +9047,7 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
#endif /* WITH_WSREP */
{
#ifdef WITH_WSREP
+ // following is historic name, mean kill_me_pls_no_mutex now
DEBUG_SYNC(thd, "before_awake_no_mutex");
if (tmp->wsrep_aborter && tmp->wsrep_aborter != thd->thread_id)
{
@@ -9060,7 +9061,7 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
{
WSREP_DEBUG("kill_one_thread %llu, victim: %llu wsrep_aborter %llu by signal %d",
thd->thread_id, id, tmp->wsrep_aborter, kill_signal);
- tmp->awake_no_mutex(kill_signal);
+ tmp->kill_me_pls_no_mutex(kill_signal);
WSREP_DEBUG("victim: %llu taken care of", id);
error= 0;
}
@@ -9152,7 +9153,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
THD *ptr= it2++;
do
{
- ptr->awake_no_mutex(kill_signal);
+ ptr->kill_me_pls_no_mutex(kill_signal);
/*
Careful here: The list nodes are allocated on the memroots of the
THDs to be awakened.
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 4a1484df2c2..81f564087c9 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -3495,7 +3495,7 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
it will be slow because it will iterate through the list
again. We just to do kill the thread ourselves.
*/
- arg.thd->awake_no_mutex(KILL_SLAVE_SAME_ID);
+ arg.thd->kill_me_pls_no_mutex(KILL_SLAVE_SAME_ID);
mysql_mutex_unlock(&arg.thd->LOCK_thd_kill);
if (WSREP(arg.thd)) mysql_mutex_unlock(&arg.thd->LOCK_thd_data);
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 452690f3237..4ed4f7b270e 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -3125,7 +3125,8 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond)
explain_req.failed_to_produce= FALSE;
/* Ok, we have a lock on target->LOCK_thd_kill, can call: */
- bres= tmp->apc_target.make_apc_call(thd, &explain_req, timeout_sec, &timed_out);
+ bres= tmp->apc_target.make_apc_call(tmp, thd, &explain_req,
+ timeout_sec, &timed_out);
if (bres || explain_req.failed_to_produce)
{
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index d0155f27d6d..deda04575df 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -2574,8 +2574,11 @@ static my_bool kill_all_threads(THD *thd, THD *caller_thd)
{
/* replicated transactions must be skipped */
WSREP_DEBUG("closing connection %lld", (longlong) thd->thread_id);
- /* instead of wsrep_close_thread() we do now soft kill by THD::awake */
- thd->awake(KILL_CONNECTION);
+ /*
+ instead of wsrep_close_thread() we do now soft kill by
+ THD::kill_me_pls
+ */
+ thd->kill_me_pls(KILL_CONNECTION);
}
}
return 0;
diff --git a/unittest/sql/my_apc-t.cc b/unittest/sql/my_apc-t.cc
index c08e7281c92..9bf26463668 100644
--- a/unittest/sql/my_apc-t.cc
+++ b/unittest/sql/my_apc-t.cc
@@ -151,7 +151,7 @@ void *test_apc_requestor_thread(void *ptr)
bool timed_out;
mysql_mutex_lock(&target_mutex);
- bool res= apc_target.make_apc_call(&my_thd, &apc_order, 60, &timed_out);
+ bool res= apc_target.make_apc_call(NULL, &my_thd, &apc_order, 60, &timed_out);
if (res)
{
if (timed_out)