diff --git a/mysql-test/main/rli_run_lock.result b/mysql-test/main/rli_run_lock.result new file mode 100644 index 0000000000000..e2776a356d0d2 --- /dev/null +++ b/mysql-test/main/rli_run_lock.result @@ -0,0 +1,18 @@ +CHANGE MASTER TO master_host='127.0.0.1', master_user='root'; +START SLAVE SQL_THREAD; +include/wait_for_slave_sql_to_start.inc +SET @@SESSION.debug_sync= +'hold_sss_with_run_lock SIGNAL sss_got_run_lock WAIT_FOR sss_continue'; +SHOW SLAVE STATUS; +connect stopper, 127.0.0.1, root, , , $SERVER_MYPORT_1; +SET @@SESSION.debug_sync= 'now WAIT_FOR sss_got_run_lock'; +STOP SLAVE SQL_THREAD; +connect continuer, 127.0.0.1, root, , , $SERVER_MYPORT_1; +SET @@SESSION.debug_sync= 'now SIGNAL sss_continue'; +connection stopper; +disconnect continuer; +connection default; +disconnect stopper; +SET @@SESSION.debug_sync= RESET; +include/wait_for_slave_sql_to_stop.inc +RESET SLAVE ALL; diff --git a/mysql-test/main/rli_run_lock.test b/mysql-test/main/rli_run_lock.test new file mode 100644 index 0000000000000..ca8eaf4d92943 --- /dev/null +++ b/mysql-test/main/rli_run_lock.test @@ -0,0 +1,43 @@ +# MDEV-40298 +# Use-After-Free when SQL Thread stops in the middle of SHOW SLAVE STATUS +# +# Test that the correct synchronization is performed + +--source include/have_debug_sync.inc +--source include/have_binlog_format_mixed.inc # No actual replication required +CHANGE MASTER TO master_host='127.0.0.1', master_user='root'; # basic setup + +START SLAVE SQL_THREAD; +--source include/wait_for_slave_sql_to_start.inc + + +SET @@SESSION.debug_sync= + 'hold_sss_with_run_lock SIGNAL sss_got_run_lock WAIT_FOR sss_continue'; +--send SHOW SLAVE STATUS + +--connect (stopper, 127.0.0.1, root, , , $SERVER_MYPORT_1) + SET @@SESSION.debug_sync= 'now WAIT_FOR sss_got_run_lock'; + --send STOP SLAVE SQL_THREAD + # Wait a bit for the thread to "shut down" + # (It should not shut down, but block waiting for the ongoing SSS; + # the tested bug instead pulled this carpet under the SSS's feet.) + --sleep 1 + + --connect (continuer, 127.0.0.1, root, , , $SERVER_MYPORT_1) + SET @@SESSION.debug_sync= 'now SIGNAL sss_continue'; + --connection stopper + --disconnect continuer + + --reap +--connection default +--disconnect stopper + + +--disable_result_log + --reap +--enable_result_log + +# Clean-up +SET @@SESSION.debug_sync= RESET; +--source include/wait_for_slave_sql_to_stop.inc +RESET SLAVE ALL; diff --git a/sql/slave.cc b/sql/slave.cc index 370b2509a1e18..9ca95dee93851 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3301,10 +3301,13 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, protocol->store(mi->connection_name.str, mi->connection_name.length, &my_charset_bin); - mysql_mutex_lock(&mi->run_lock); + mysql_mutex_lock(&mi->rli.run_lock); THD *sql_thd= mi->rli.sql_driver_thd; + DEBUG_SYNC(thd, "hold_sss_with_run_lock"); const char *slave_sql_running_state= sql_thd ? sql_thd->get_proc_info() : ""; + mysql_mutex_unlock(&mi->rli.run_lock); + mysql_mutex_lock(&mi->run_lock); THD *io_thd= mi->io_thd; const char *slave_io_running_state= io_thd ? io_thd->get_proc_info() : ""; mysql_mutex_unlock(&mi->run_lock);