diff --git a/mysql-test/suite/galera/r/MDEV-36116.result b/mysql-test/suite/galera/r/MDEV-36116.result new file mode 100644 index 0000000000000..11899b9c09bce --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-36116.result @@ -0,0 +1,22 @@ +connection node_2; +connection node_1; +connect con1,127.0.0.1,root,,test,$NODE_MYPORT_1; +connection node_1; +CALL mtr.add_suppression("CREATE TABLE isolation failure"); +SET DEBUG_SYNC = 'wsrep_kill_thd_before_enter_toi SIGNAL may_kill WAIT_FOR continue'; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +connection con1; +SET DEBUG_SYNC = 'now WAIT_FOR may_kill'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +connection node_1; +ERROR HY000: Lost connection to MySQL server during query +connection node_2; +SHOW TABLES LIKE 't1'; +Tables_in_test (t1) +connection con1; +SHOW TABLES LIKE 't1'; +Tables_in_test (t1) +SET DEBUG_SYNC = 'RESET'; +disconnect con1; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/t/MDEV-36116.test b/mysql-test/suite/galera/t/MDEV-36116.test new file mode 100644 index 0000000000000..6d638f04177c7 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-36116.test @@ -0,0 +1,42 @@ +# +# MDEV-36116: TOI crashes in debug assert if executing thread is killed. +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connect con1,127.0.0.1,root,,test,$NODE_MYPORT_1 + +# Start TOI operation and wait for the thread to be killed. +--connection node_1 +CALL mtr.add_suppression("CREATE TABLE isolation failure"); + +--let $connection_id = `SELECT CONNECTION_ID()` +SET DEBUG_SYNC = 'wsrep_kill_thd_before_enter_toi SIGNAL may_kill WAIT_FOR continue'; +--send + CREATE TABLE t1 (a INT) ENGINE=InnoDB; + +# Kill the thread and let it continue. +--connection con1 +SET DEBUG_SYNC = 'now WAIT_FOR may_kill'; +--disable_query_log +--eval KILL CONNECTION $connection_id +--enable_query_log +SET DEBUG_SYNC = 'now SIGNAL continue'; + +--connection node_1 +--error 2013 +--reap + +# Verify no tables created on either nodes. +--connection node_2 +SHOW TABLES LIKE 't1'; + +--connection con1 +SHOW TABLES LIKE 't1'; + +# Cleanup +SET DEBUG_SYNC = 'RESET'; +--disconnect con1 +--source include/galera_end.inc diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 974ddfc1d4c65..77ebfc5b5b4b8 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2621,12 +2621,13 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, const wsrep::key_array *fk_tables, const HA_CREATE_INFO *create_info) { + DEBUG_SYNC(thd, "wsrep_kill_thd_before_enter_toi"); mysql_mutex_lock(&thd->LOCK_thd_kill); const killed_state killed = thd->killed; mysql_mutex_unlock(&thd->LOCK_thd_kill); if (killed) { - DBUG_ASSERT(FALSE); + /* The thread may have been killed as a result of memory pressure. */ return -1; } @@ -2698,6 +2699,10 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, if (thd->variables.wsrep_on && wsrep_thd_is_local(thd)) { + mysql_mutex_lock(&thd->LOCK_thd_kill); + if (thd->killed) wsrep_backup_kill_for_commit(thd); + mysql_mutex_unlock(&thd->LOCK_thd_kill); + switch (wsrep_OSU_method_get(thd)) { case WSREP_OSU_TOI: ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info, fk_tables, @@ -2728,9 +2733,12 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, case 1: /* TOI replication skipped, treat as success */ ret= 0; - break; + /* fall through */ case -1: /* TOI replication failed, treat as error */ + mysql_mutex_lock(&thd->LOCK_thd_kill); + wsrep_restore_kill_after_commit(thd); + mysql_mutex_unlock(&thd->LOCK_thd_kill); break; } } @@ -2759,6 +2767,13 @@ void wsrep_to_isolation_end(THD *thd) DBUG_ASSERT(0); } if (wsrep_emulate_bin_log) wsrep_thd_binlog_trx_reset(thd); + + mysql_mutex_lock(&thd->LOCK_thd_kill); + if (thd->wsrep_abort_by_kill != NOT_KILLED) + { + wsrep_restore_kill_after_commit(thd); + } + mysql_mutex_unlock(&thd->LOCK_thd_kill); } #define WSREP_MDL_LOG(severity, msg, schema, schema_len, req, gra) \ diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 2c2e3a0e44d03..0d157cf19ba26 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -496,7 +496,6 @@ void wsrep_backup_kill_for_commit(THD *thd) void wsrep_restore_kill_after_commit(THD *thd) { - DBUG_ASSERT(wsrep_is_active(thd)); mysql_mutex_assert_owner(&thd->LOCK_thd_kill); thd->killed= thd->wsrep_abort_by_kill; my_free(thd->killed_err);