From 42c58b87da01fdf41ae5aa0d41af226d41096262 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Wed, 17 Apr 2019 15:32:30 +0300 Subject: [PATCH] MDEV-18096 The server would crash when has configs rpl_semi_sync_master_enabled = OFF rpl_semi_sync_master_wait_no_slave = OFF The patch fixes a fired assert in the semisync master module. The assert caught attempt to switch semisync off (per rpl_semi_sync_master_wait_no_slave = OFF) when it was not even initialized (per rpl_semi_sync_master_enabled = OFF). The switching-off execution branch is relocated under one that executes enable_master() first. A minor cleaup is done to remove the int return from two functions that did not return anything but an error which could not happen in the functions. --- .../rpl/r/rpl_semi_sync_wait_no_slave.result | 8 ++++++ .../t/rpl_semi_sync_wait_no_slave-master.opt | 1 + .../rpl/t/rpl_semi_sync_wait_no_slave.test | 14 ++++++++++ sql/semisync_master.cc | 27 +++++++++---------- sql/semisync_master.h | 7 ++--- 5 files changed, 38 insertions(+), 19 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_semi_sync_wait_no_slave.result create mode 100644 mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt create mode 100644 mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_wait_no_slave.result b/mysql-test/suite/rpl/r/rpl_semi_sync_wait_no_slave.result new file mode 100644 index 00000000000..4bf6af2714d --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_wait_no_slave.result @@ -0,0 +1,8 @@ +include/master-slave.inc +[connection master] +connection master; +CREATE TABLE t1 (a INT); +INSERT INTO t1 SET a=1; +DROP TABLE t1; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt new file mode 100644 index 00000000000..d84ebab5d56 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt @@ -0,0 +1 @@ +--rpl_semi_sync_master_enabled=0 --rpl_semi_sync_master_wait_no_slave=0 diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test new file mode 100644 index 00000000000..fecd0e25cb2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test @@ -0,0 +1,14 @@ +# The test verifies master crash of MDEV-18096 when the server starts with +# rpl_semi_sync_master_enabled = OFF rpl_semi_sync_master_wait_no_slave = OFF + +--source include/master-slave.inc +--source include/have_binlog_format_mixed.inc + +--connection master +CREATE TABLE t1 (a INT); +INSERT INTO t1 SET a=1; +DROP TABLE t1; + +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc index 8a82fd9085c..4e37e3af58d 100644 --- a/sql/semisync_master.cc +++ b/sql/semisync_master.cc @@ -228,7 +228,7 @@ bool Active_tranx::is_tranx_end_pos(const char *log_file_name, DBUG_RETURN(entry != NULL); } -int Active_tranx::clear_active_tranx_nodes(const char *log_file_name, +void Active_tranx::clear_active_tranx_nodes(const char *log_file_name, my_off_t log_file_pos) { Tranx_node *new_front; @@ -307,7 +307,7 @@ int Active_tranx::clear_active_tranx_nodes(const char *log_file_name, m_trx_front->log_name, (ulong)m_trx_front->log_pos)); } - DBUG_RETURN(0); + DBUG_VOID_RETURN; } @@ -371,20 +371,21 @@ int Repl_semi_sync_master::init_object() { result = enable_master(); if (!result) + { result= ack_receiver.start(); /* Start the ACK thread. */ + /* + If rpl_semi_sync_master_wait_no_slave is disabled, let's temporarily + switch off semisync to avoid hang if there's none active slave. + */ + if (!rpl_semi_sync_master_wait_no_slave) + switch_off(); + } } else { result = disable_master(); } - /* - If rpl_semi_sync_master_wait_no_slave is disabled, let's temporarily - switch off semisync to avoid hang if there's none active slave. - */ - if (!rpl_semi_sync_master_wait_no_slave) - switch_off(); - return result; } @@ -961,17 +962,15 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, * the current sending event catches up with last wait position. If it * does match, semi-sync will be switched on again. */ -int Repl_semi_sync_master::switch_off() +void Repl_semi_sync_master::switch_off() { - int result; - DBUG_ENTER("Repl_semi_sync_master::switch_off"); m_state = false; /* Clear the active transaction list. */ assert(m_active_tranxs != NULL); - result = m_active_tranxs->clear_active_tranx_nodes(NULL, 0); + m_active_tranxs->clear_active_tranx_nodes(NULL, 0); rpl_semi_sync_master_off_times++; m_wait_file_name_inited = false; @@ -979,7 +978,7 @@ int Repl_semi_sync_master::switch_off() sql_print_information("Semi-sync replication switched OFF."); cond_broadcast(); /* wake up all waiting threads */ - DBUG_RETURN(result); + DBUG_VOID_RETURN; } int Repl_semi_sync_master::try_switch_on(int server_id, diff --git a/sql/semisync_master.h b/sql/semisync_master.h index 3b05d9e0348..de5e3240802 100644 --- a/sql/semisync_master.h +++ b/sql/semisync_master.h @@ -343,11 +343,8 @@ public: * position. * If log_file_name is NULL, everything will be cleared: the sorted * list and the hash table will be reset to empty. - * - * Return: - * 0: success; non-zero: error */ - int clear_active_tranx_nodes(const char *log_file_name, + void clear_active_tranx_nodes(const char *log_file_name, my_off_t log_file_pos); /* Given a position, check to see whether the position is an active @@ -449,7 +446,7 @@ class Repl_semi_sync_master } /* Switch semi-sync off because of timeout in transaction waiting. */ - int switch_off(); + void switch_off(); /* Switch semi-sync on when slaves catch up. */ int try_switch_on(int server_id,