revision-id: a97c190d95bc9f3be0c0fa75abe56422927e7d82 (mariadb-10.3.7-98-ga97c190d95b) parent(s): 93b6552182740d1a66cf41c30811e7275d31b07f author: Andrei Elkin committer: Andrei Elkin timestamp: 2018-07-26 10:54:13 +0300 message: MDEV-16812 Semisync slave io thread segfaults at STOP-SLAVE handling When the semisync slave is being stopped with STOP SLAVE just after the master was shut down it attempts to reconnect with the master anyway per a semisync routine. Instead of an expected error the io-thread segfauls in mysql_real_connect() execution at !mysql->options.extension->async_context check trying to reach the extension's member while mysql->options.extension is actually and correctly NULL. Apparently not-NULL check for mysql->options.extension was missed and it's deployed by the patch to fix this issue. As a bonus it also tackles an assert Thread 0x7f16c72148c0 (LWP 24639) 0x00007f16c53b3bf2 in __GI___assert_fail (assertion=0x55a686117558 "global_status_var.global_memory_used == 0", file=0x55a6861171e8 "/home/andrei/MDB/WTs/10.3-clean/sql/mysqld.cc", line=2201, function=0x55a68611fa80 <mysqld_exit(int)::__PRETTY_FUNCTION__> "void mysqld_exit(int)") at assert.c:101 in a new test of the patch. The reason of the assert was insufficient cleanup in Repl_semi_sync_slave::kill_connection() which has a branch where a MYSQL instance was left out unfred. --- .../rpl/r/rpl_semi_sync_master_shutdown.result | 33 ++++++++++++ .../suite/rpl/t/rpl_semi_sync_master_shutdown.test | 60 ++++++++++++++++++++++ sql-common/client.c | 2 +- sql/semisync_slave.cc | 3 +- 4 files changed, 95 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result b/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result new file mode 100644 index 00000000000..786e1682bb0 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result @@ -0,0 +1,33 @@ +include/master-slave.inc +[connection master] +connection master; +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; +connection slave; +include/stop_slave.inc +SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1; +include/start_slave.inc +connection master; +CREATE TABLE t1 (a INT); +INSERT INTO t1 SET a=1; +connection slave; +connection master; +# Shutdown master +include/rpl_stop_server.inc [server_number=1] +connection slave; +include/stop_slave.inc +# Restart master +include/rpl_start_server.inc [server_number=1] +connection slave; +include/stop_slave.inc +Warnings: +Note 1255 Slave already has been stopped +include/start_slave.inc +connection master; +SET @@GLOBAL.debug_dbug=""; +SET @@GLOBAL. rpl_semi_sync_master_enabled = 0; +connection master; +DROP TABLE t1; +connection slave; +include/stop_slave.inc +SET @@GLOBAL. rpl_semi_sync_slave_enabled = 0; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test new file mode 100644 index 00000000000..2224f78d6d0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test @@ -0,0 +1,60 @@ +# MDEV-16812 Semisync slave io thread segfaults at STOP-SLAVE handling +# +# The test verifies that the semisync-enabled slave io thread +# finishes off as specified in particular trying to connect even to a shut down +# master for a semisync firewell routine. + +source include/not_embedded.inc; +source include/have_debug.inc; +source include/master-slave.inc; + +--connection master + +--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled ` +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; + +--connection slave +source include/stop_slave.inc; +--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled ` +SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1; +source include/start_slave.inc; + +--connection master +CREATE TABLE t1 (a INT); +INSERT INTO t1 SET a=1; + +--sync_slave_with_master + +connection master; +--echo # Shutdown master +--let $rpl_server_number=1 +source include/rpl_stop_server.inc; + +--connection slave +--source include/stop_slave.inc + +#connection master; +--echo # Restart master +--let $rpl_server_number=1 +source include/rpl_start_server.inc; + +# +# Clean up +# +--connection slave +--source include/stop_slave.inc +--source include/start_slave.inc + +--connection master +SET @@GLOBAL.debug_dbug=""; +--eval SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master + +--connection master +DROP TABLE t1; + +--sync_slave_with_master +source include/stop_slave.inc; +--eval SET @@GLOBAL. rpl_semi_sync_slave_enabled = $sav_enabled_slave + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/sql-common/client.c b/sql-common/client.c index 088377f8c52..8bbe08a504a 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -3657,7 +3657,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, end_server(mysql); mysql_close_free(mysql); if (!(client_flag & CLIENT_REMEMBER_OPTIONS) && - !mysql->options.extension->async_context) + !(mysql->options.extension && mysql->options.extension->async_context)) mysql_close_free_options(mysql); } DBUG_RETURN(0); diff --git a/sql/semisync_slave.cc b/sql/semisync_slave.cc index 86d0176dac1..df8baf045ac 100644 --- a/sql/semisync_slave.cc +++ b/sql/semisync_slave.cc @@ -144,8 +144,7 @@ void Repl_semi_sync_slave::kill_connection(MYSQL *mysql) { sql_print_information("cannot connect to master to kill slave io_thread's " "connection"); - if (!ret) - mysql_close(kill_mysql); + mysql_close(kill_mysql); return; } size_t kill_buffer_length = my_snprintf(kill_buffer, 30, "KILL %lu",