diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result index 15c069ab68d..1326c7491f5 100644 --- a/mysql-test/r/rpl_temporary.result +++ b/mysql-test/r/rpl_temporary.result @@ -133,3 +133,22 @@ select * from t1; a 1 drop table t1; +DROP TABLE IF EXISTS t1; +CREATE TEMPORARY TABLE t1 (a char(1)); +INSERT INTO t1 VALUES ('a'); +include/stop_slave.inc +include/start_slave.inc +INSERT INTO t1 VALUES ('b'); +DROP TABLE IF EXISTS t1; +CREATE TEMPORARY TABLE `t1`(`a` tinyint,`b` char(1))engine=myisam; +INSERT INTO `t1` set `a`=128,`b`='128'; +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1265 Data truncated for column 'b' at row 1 +include/stop_slave.inc +include/start_slave.inc +INSERT INTO `t1` set `a`=128,`b`='128'; +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1265 Data truncated for column 'b' at row 1 +DROP TABLE t1; diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index 516f3a026c9..4cd538877eb 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -217,4 +217,74 @@ drop table t1; # Delete the anonymous users source include/delete_anonymous_users.inc; +# ################################################################## +# BUG#41725: slave crashes when inserting into temporary table after +# stop/start slave +# +# This test checks that both reported issues (assertion failure and +# crash) go away. It is implemented as follows: +# +# case 1: assertion failure +# i) create and insert into temporary table on master +# ii) sync slave with master +# iii) stop and restart slave +# iv) insert into master another value +# v) sync slave with master +# +# +# case 2: crash (SIGSEV) +# i) create and insert into temporary table on master (insert +# produces warnings) +# ii) sync slave with master +# iii) stop and restart slave +# iv) insert into master more values +# v) sync slave with master + +# case 1: Assertion in Field_string::store() failed because current +# thread reference differed from table->in_use after slave +# restart + +connection master; + +disable_warnings; +DROP TABLE IF EXISTS t1; +enable_warnings; + +CREATE TEMPORARY TABLE t1 (a char(1)); +INSERT INTO t1 VALUES ('a'); +sync_slave_with_master; + +source include/stop_slave.inc; +source include/start_slave.inc; + +connection master; +INSERT INTO t1 VALUES ('b'); +sync_slave_with_master; + +# case 2: crash on sp_rcontext::find_handler because it used +# reference to invalid THD object after slave restart + +connection master; + +disable_warnings; +DROP TABLE IF EXISTS t1; +enable_warnings; +CREATE TEMPORARY TABLE `t1`(`a` tinyint,`b` char(1))engine=myisam; +INSERT INTO `t1` set `a`=128,`b`='128'; + +sync_slave_with_master; + +source include/stop_slave.inc; +source include/start_slave.inc; + +connection master; +INSERT INTO `t1` set `a`=128,`b`='128'; +sync_slave_with_master; + +# cleanup + +connection master; +DROP TABLE t1; +sync_slave_with_master; + # End of 5.0 tests diff --git a/sql/slave.cc b/sql/slave.cc index f29936c5942..88c19a04602 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -545,6 +545,14 @@ void st_relay_log_info::close_temporary_tables() slave_open_temp_tables= 0; } +static void set_thd_in_use_temporary_tables(RELAY_LOG_INFO *rli) +{ + TABLE *table; + + for (table= rli->save_temporary_tables ; table ; table= table->next) + table->in_use= rli->sql_thd; +} + /* purge_relay_logs() @@ -3964,6 +3972,7 @@ slave_begin: } thd->init_for_queries(); thd->temporary_tables = rli->save_temporary_tables; // restore temp tables + set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables pthread_mutex_lock(&LOCK_thread_count); threads.append(thd); pthread_mutex_unlock(&LOCK_thread_count); @@ -4136,6 +4145,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ DBUG_ASSERT(rli->sql_thd == thd); THD_CHECK_SENTRY(thd); rli->sql_thd= 0; + set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables pthread_mutex_lock(&LOCK_thread_count); THD_CHECK_SENTRY(thd); delete thd;