Skip to content

Commit e84e5a3

Browse files
committed
MDEV-40298 Use-After-Free when SQL Thread stops in the middle of SHOW SLAVE STATUS
MDEV-36287 acknowledged that SHOW SLAVE STATUS needed to acquire a mutex lock before accessing the SQL Thread’s THD, as otherwise it may access invalid memory if a concurrent STOP SLAVE deletes the THD. But it missed that the SQL Thread’s mutex is `mi->rli.run_lock`, not `mi->run_lock`, so the bug was still not fixed. This commit fills the oversight in by acquiring the correct corresponding lock for each of `Slave_IO_State` & `Slave_SQL_State`.
1 parent 85ab366 commit e84e5a3

3 files changed

Lines changed: 63 additions & 1 deletion

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CHANGE MASTER TO master_host='127.0.0.1', master_user='root';
2+
START SLAVE SQL_THREAD;
3+
include/wait_for_slave_sql_to_start.inc
4+
SET @save_dbug= @@GLOBAL.debug_dbug;
5+
SET @@GLOBAL.debug_dbug= '+d,hold_sss_with_run_lock';
6+
SHOW SLAVE STATUS;
7+
connect stopper, 127.0.0.1, root, , , $SERVER_MYPORT_1;
8+
SET @@SESSION.debug_sync= 'now WAIT_FOR sss_got_run_lock';
9+
STOP SLAVE SQL_THREAD;
10+
connect continuer, 127.0.0.1, root, , , $SERVER_MYPORT_1;
11+
SET @@SESSION.debug_sync= 'now SIGNAL sss_continue';
12+
connection stopper;
13+
disconnect continuer;
14+
connection default;
15+
disconnect stopper;
16+
SET @@GLOBAL.debug_dbug= @save_dbug;
17+
SET @@SESSION.debug_sync= RESET;
18+
include/wait_for_slave_sql_to_stop.inc

mysql-test/main/rli_run_lock.test

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--source include/have_debug.inc
2+
--source include/have_debug_sync.inc
3+
--source include/have_binlog_format_mixed.inc # No actual replication required
4+
CHANGE MASTER TO master_host='127.0.0.1', master_user='root'; # basic setup
5+
6+
START SLAVE SQL_THREAD;
7+
--source include/wait_for_slave_sql_to_start.inc
8+
9+
10+
SET @save_dbug= @@GLOBAL.debug_dbug;
11+
SET @@GLOBAL.debug_dbug= '+d,hold_sss_with_run_lock';
12+
--send SHOW SLAVE STATUS
13+
14+
--connect (stopper, 127.0.0.1, root, , , $SERVER_MYPORT_1)
15+
SET @@SESSION.debug_sync= 'now WAIT_FOR sss_got_run_lock';
16+
--send STOP SLAVE SQL_THREAD
17+
# Wait a bit for the thread to "shut down"
18+
# (It should not shut down, but block waiting for the ongoing SSS;
19+
# the bug instead pulls this carpet under the SSS's feet.)
20+
--sleep 3
21+
22+
--connect (continuer, 127.0.0.1, root, , , $SERVER_MYPORT_1)
23+
SET @@SESSION.debug_sync= 'now SIGNAL sss_continue';
24+
--connection stopper
25+
--disconnect continuer
26+
27+
--reap
28+
--connection default
29+
--disconnect stopper
30+
31+
32+
--disable_result_log
33+
--reap
34+
--enable_result_log
35+
36+
SET @@GLOBAL.debug_dbug= @save_dbug;
37+
SET @@SESSION.debug_sync= RESET;
38+
--source include/wait_for_slave_sql_to_stop.inc

sql/slave.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3301,10 +3301,16 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full,
33013301
protocol->store(mi->connection_name.str, mi->connection_name.length,
33023302
&my_charset_bin);
33033303

3304-
mysql_mutex_lock(&mi->run_lock);
3304+
mysql_mutex_lock(&mi->rli.run_lock);
33053305
THD *sql_thd= mi->rli.sql_driver_thd;
3306+
DBUG_EXECUTE_IF("hold_sss_with_run_lock",
3307+
DBUG_ASSERT(!debug_sync_set_action(thd,
3308+
STRING_WITH_LEN("now SIGNAL sss_got_run_lock WAIT_FOR sss_continue")));
3309+
);
33063310
const char *slave_sql_running_state=
33073311
sql_thd ? sql_thd->get_proc_info() : "";
3312+
mysql_mutex_unlock(&mi->rli.run_lock);
3313+
mysql_mutex_lock(&mi->run_lock);
33083314
THD *io_thd= mi->io_thd;
33093315
const char *slave_io_running_state= io_thd ? io_thd->get_proc_info() : "";
33103316
mysql_mutex_unlock(&mi->run_lock);

0 commit comments

Comments
 (0)