diff options
-rw-r--r-- | mysql-test/r/truncate_coverage.result | 27 | ||||
-rw-r--r-- | mysql-test/t/truncate_coverage.test | 54 | ||||
-rw-r--r-- | sql/sql_truncate.cc | 7 |
3 files changed, 88 insertions, 0 deletions
diff --git a/mysql-test/r/truncate_coverage.result b/mysql-test/r/truncate_coverage.result index a7a4b9c70f4..728702f7ab5 100644 --- a/mysql-test/r/truncate_coverage.result +++ b/mysql-test/r/truncate_coverage.result @@ -78,3 +78,30 @@ COMMIT; UNLOCK TABLES; DROP TABLE t1; SET DEBUG_SYNC='RESET'; +# +# Bug#57659 Segfault in Query_cache::invalidate_data for TRUNCATE TABLE +# +# Note that this test case only reproduces the problem +# when it is run with valgrind. +DROP TABLE IF EXISTS t1, m1; +CREATE TABLE t1(a INT) engine=memory; +CREATE TABLE m1(a INT) engine=merge UNION(t1); +# Connection con1 +SET DEBUG_SYNC= 'open_tables_after_open_and_process_table SIGNAL opened WAIT_FOR dropped'; +# Sending: +TRUNCATE TABLE m1; +# Connection con2 +SET DEBUG_SYNC= 'now WAIT_FOR opened'; +# Sending: +FLUSH TABLES; +# Connection default +# Waiting for FLUSH TABLES to be blocked. +SET DEBUG_SYNC= 'now SIGNAL dropped'; +# Connection con1 +# Reaping: TRUNCATE TABLE m1 +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +# Connection con2 +# Reaping: FLUSH TABLES +# Connection default +SET DEBUG_SYNC= 'RESET'; +DROP TABLE m1, t1; diff --git a/mysql-test/t/truncate_coverage.test b/mysql-test/t/truncate_coverage.test index c9c4bd90ca4..135935b53b3 100644 --- a/mysql-test/t/truncate_coverage.test +++ b/mysql-test/t/truncate_coverage.test @@ -172,3 +172,57 @@ UNLOCK TABLES; DROP TABLE t1; SET DEBUG_SYNC='RESET'; +--echo # +--echo # Bug#57659 Segfault in Query_cache::invalidate_data for TRUNCATE TABLE +--echo # + +--echo # Note that this test case only reproduces the problem +--echo # when it is run with valgrind. + +--disable_warnings +DROP TABLE IF EXISTS t1, m1; +--enable_warnings + +CREATE TABLE t1(a INT) engine=memory; +CREATE TABLE m1(a INT) engine=merge UNION(t1); +connect(con2, localhost, root); + +--echo # Connection con1 +connect(con1, localhost, root); +SET DEBUG_SYNC= 'open_tables_after_open_and_process_table SIGNAL opened WAIT_FOR dropped'; +--echo # Sending: +--send TRUNCATE TABLE m1 + +--echo # Connection con2 +connection con2; +SET DEBUG_SYNC= 'now WAIT_FOR opened'; +--echo # Sending: +--send FLUSH TABLES + +--echo # Connection default +connection default; +--echo # Waiting for FLUSH TABLES to be blocked. +let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.processlist + WHERE state= 'Waiting for table flush' AND info= 'FLUSH TABLES'; +--source include/wait_condition.inc +SET DEBUG_SYNC= 'now SIGNAL dropped'; + +--echo # Connection con1 +connection con1; +--echo # Reaping: TRUNCATE TABLE m1 +--error ER_WRONG_MRG_TABLE +--reap +disconnect con1; +--source include/wait_until_disconnected.inc + +--echo # Connection con2 +connection con2; +--echo # Reaping: FLUSH TABLES +--reap +disconnect con2; +--source include/wait_until_disconnected.inc + +--echo # Connection default +connection default; +SET DEBUG_SYNC= 'RESET'; +DROP TABLE m1, t1; diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 0cff2875ac8..909c6a08b67 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -472,6 +472,13 @@ bool Truncate_statement::truncate_table(THD *thd, TABLE_LIST *table_ref) binlog_stmt= !error || error != HA_ERR_WRONG_COMMAND; } + /* + If we tried to open a MERGE table and failed due to problems with the + children tables, the table will have been closed and table_ref->table + will be invalid. Reset the pointer here in any case as + query_cache_invalidate does not need a valid TABLE object. + */ + table_ref->table= NULL; query_cache_invalidate3(thd, table_ref, FALSE); } |