Skip to content

Commit 652402d

Browse files
committed
BUG#31490241 - X.ADMIN_XKILL FAILS WITH VALGRIND ERRORS ON PB2
Description =========== The issue is a race-condition, seen when a user tries to list all session, and there is one "Srv-session" in middle of closure. The "pluggable protocol" is removed from "Srv-session", and session is left with "text-protocol" instance. Listing such session causes access to not initialized data, required by "text-protocol" instance. Fix === At session closure, the patch is going to reverse the deinitialization sequence. First it is going to remove the `THD` from global container of all THDs, after that it is going to pop "pluggable protocol" from protocol stack. The session wont be visible in any session-lists after removing `THD` from global container, thus its safe to pop the "pluggable protocol". RB: 24698 Reviewed by: Grzegorz Szwarc <grzegorz.szwarc@oracle.com> Reviewed-by: Catalin Besleaga <catalin.besleaga@oracle.com>
1 parent 4ba5803 commit 652402d

File tree

4 files changed

+130
-2
lines changed

4 files changed

+130
-2
lines changed
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
## I. Reproduce race condition between closing session and listing
2+
# session (BUG#31490241):
3+
# 1. Create X Protocol session(X1) using "x_root" account and hang it while closing
4+
# (sync point: srv_session_close)
5+
# 2. Create classic protocol session(C1) and list all session,
6+
# hang it at "x_root" row generation while waking X1
7+
# 3. Wait until the X1, is inside THD deregistration
8+
# and wakeup C1
9+
# 4. Show at C1, processlist results
10+
11+
# Adding debug point 'test_fill_proc_with_x_root' to @@GLOBAL.debug
12+
SET DEBUG_SYNC= 'fill_proc_list_with_x_root SIGNAL listing_x_root WAIT_FOR continue_fill_proc';
13+
14+
#
15+
# I.1 connect X1
16+
RUN SET DEBUG_SYNC= 'srv_session_close WAIT_FOR listing_x_root'
17+
18+
0 rows affected
19+
Mysqlx.Ok {
20+
msg: "bye!"
21+
}
22+
ok
23+
24+
#
25+
# I.2 Use C1 and list all sessions
26+
SELECT user from information_schema.processlist order by user;
27+
28+
#
29+
# I.3
30+
SET DEBUG_SYNC= 'now SIGNAL continue_fill_proc';
31+
32+
#
33+
# I.4
34+
user
35+
event_scheduler
36+
root
37+
root
38+
x_root
39+
# Removing debug point 'test_fill_proc_with_x_root' from @@GLOBAL.debug
+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
## This test-case was created for reproducing a Valgrind issue that occure
2+
# between two session, one lising all session and second that is closing.
3+
4+
--source include/have_debug_sync.inc
5+
--source include/have_debug.inc
6+
--source ../include/have_performance_schema_events_waits_history.inc
7+
8+
--source include/xplugin_preamble.inc
9+
--source include/xplugin_create_user.inc
10+
11+
--echo ## I. Reproduce race condition between closing session and listing
12+
--echo # session (BUG#31490241):
13+
--echo # 1. Create X Protocol session(X1) using "x_root" account and hang it while closing
14+
--echo # (sync point: srv_session_close)
15+
--echo # 2. Create classic protocol session(C1) and list all session,
16+
--echo # hang it at "x_root" row generation while waking X1
17+
--echo # 3. Wait until the X1, is inside THD deregistration
18+
--echo # and wakeup C1
19+
--echo # 4. Show at C1, processlist results
20+
--echo
21+
22+
## Test Setup
23+
--let $xtest_file= $MYSQL_TMP_DIR/admin_ping_mysqlx.tmp
24+
--write_file $xtest_file
25+
26+
SET DEBUG_SYNC= 'srv_session_close WAIT_FOR listing_x_root';
27+
EOF
28+
29+
--let $debug_point= test_fill_proc_with_x_root
30+
--source include/add_debug_point.inc
31+
32+
# Connect C1
33+
--connect(con1,localhost,root,,)
34+
SET DEBUG_SYNC= 'fill_proc_list_with_x_root SIGNAL listing_x_root WAIT_FOR continue_fill_proc';
35+
36+
37+
## Test execution
38+
--echo
39+
--echo #
40+
--echo # I.1 connect X1
41+
--exec $MYSQLXTEST -ux_root --password='' --file=$xtest_file 2>&1
42+
43+
--echo
44+
--echo #
45+
--echo # I.2 Use C1 and list all sessions
46+
send SELECT user from information_schema.processlist order by user;
47+
48+
49+
--echo
50+
--echo #
51+
--echo # I.3
52+
# Go back to C0, wait for X1
53+
--connection default
54+
let $wait_condition=
55+
select count(*) from performance_schema.events_waits_current
56+
where EVENT_NAME like 'wait/synch/mutex/sql/LOCK_thd_remove';
57+
--source include/wait_condition_or_abort.inc
58+
59+
# Wake up C1
60+
SET DEBUG_SYNC= 'now SIGNAL continue_fill_proc';
61+
62+
--echo
63+
--echo #
64+
--echo # I.4
65+
# Go back to C1, and receive process-list
66+
--connection con1
67+
reap;
68+
69+
## Cleanup
70+
--connection default
71+
72+
--let $debug_point= test_fill_proc_with_x_root
73+
--source include/remove_debug_point.inc
74+
--remove_file $xtest_file
75+
--source include/xplugin_drop_user.inc

sql/sql_show.cc

+6
Original file line numberDiff line numberDiff line change
@@ -2283,6 +2283,12 @@ class Fill_process_list : public Do_THD_Impl {
22832283
strcmp(inspect_sctx_user.str, user))))
22842284
return;
22852285

2286+
DBUG_EXECUTE_IF(
2287+
"test_fill_proc_with_x_root",
2288+
if (0 == strcmp(inspect_sctx_user.str, "x_root")) {
2289+
DEBUG_SYNC(m_client_thd, "fill_proc_list_with_x_root");
2290+
});
2291+
22862292
TABLE *table = m_tables->table;
22872293
restore_record(table, s->default_values);
22882294

sql/srv_session.cc

+10-2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#include "sql/auth/sql_security_ctx.h"
6161
#include "sql/conn_handler/connection_handler_manager.h"
6262
#include "sql/current_thd.h"
63+
#include "sql/debug_sync.h" // DEBUG_SYNC
6364
#include "sql/derror.h" // ER_DEFAULT
6465
#include "sql/log.h" // Query log
6566
#include "sql/mysqld.h" // current_thd
@@ -1017,6 +1018,13 @@ bool Srv_session::close() {
10171018

10181019
thd.get_stmt_da()->reset_diagnostics_area();
10191020

1021+
// DEBUG_SYNC control block is released under call to
1022+
// `thd.release_resource`, thus we can't put this sync
1023+
// point directly before `pop_protocol`.
1024+
// Second constrain is that `THD::disconnect` marks
1025+
// this connection as killed, which disables DEBUG_SYNC.
1026+
DEBUG_SYNC(&thd, "srv_session_close");
1027+
10201028
thd.disconnect();
10211029

10221030
#ifdef HAVE_PSI_THREAD_INTERFACE
@@ -1025,12 +1033,12 @@ bool Srv_session::close() {
10251033

10261034
thd.release_resources();
10271035

1036+
Global_THD_manager::get_instance()->remove_thd(&thd);
1037+
10281038
mysql_mutex_lock(&thd.LOCK_thd_protocol);
10291039
thd.pop_protocol();
10301040
mysql_mutex_unlock(&thd.LOCK_thd_protocol);
10311041

1032-
Global_THD_manager::get_instance()->remove_thd(&thd);
1033-
10341042
Connection_handler_manager::dec_connection_count();
10351043

10361044
return false;

0 commit comments

Comments
 (0)