#At file:///export/home/x/mysql-5.5-runtime-bug56494/ based on revid:jon.hauglid@stripped
3134 Jon Olav Hauglid 2010-09-09
Bug #56494 Segfault in upgrade_shared_lock_to_exclusive() for
REPAIR of merge table
This crash happened if a table maintenance statement (ANALYZE TABLE,
REPAIR TABLE, etc.) was executed on a MERGE table and opening and
locking a child table failed. This could for example happen if a child
table did not exist or if a lock timeout happened while waiting for
a conflicting metadata lock to disappear.
Since opening and locking the MERGE table and its children failed,
the tables would be closed and the metadata locks released.
However, TABLE_LIST::table for the MERGE table would still be set,
with its value invalid since the tables had been closed.
This caused the table maintenance statement to try to continue
and upgrade the metadata lock on the MERGE table. But since the lock
already had been released, this caused a segfault.
This patch fixes the problem by setting TABLE_LIST::table to NULL
if open_and_lock_tables() fails. This prevents the maintenance
statement from continuing and trying to upgrade the metadata lock.
The patch also fixes a problem where REPAIR TABLE ... USE_FRM
would cause an assert for MERGE tables, even if child tables
were opened successfully.
Test case added to mdl_sync.test.
modified:
mysql-test/r/log_tables_upgrade.result
mysql-test/r/mdl_sync.result
mysql-test/r/merge.result
mysql-test/r/myisampack.result
mysql-test/r/mysql_upgrade.result
mysql-test/r/mysql_upgrade_ssl.result
mysql-test/t/mdl_sync.test
sql/sql_admin.cc
=== modified file 'mysql-test/r/log_tables_upgrade.result'
--- a/mysql-test/r/log_tables_upgrade.result 2010-02-26 12:22:48 +0000
+++ b/mysql-test/r/log_tables_upgrade.result 2010-09-09 07:50:04 +0000
@@ -19,7 +19,7 @@ mysql.event
mysql.func OK
mysql.general_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.help_category OK
mysql.help_keyword OK
mysql.help_relation OK
@@ -33,7 +33,7 @@ mysql.renamed_general_log
mysql.servers OK
mysql.slow_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.tables_priv OK
mysql.time_zone OK
mysql.time_zone_leap_second OK
@@ -41,6 +41,10 @@ mysql.time_zone_name
mysql.time_zone_transition OK
mysql.time_zone_transition_type OK
mysql.user OK
+
+Repairing tables
+mysql.general_log OK
+mysql.slow_log OK
DROP TABLE general_log;
RENAME TABLE renamed_general_log TO general_log;
SET GLOBAL general_log = @saved_general_log;
=== modified file 'mysql-test/r/mdl_sync.result'
--- a/mysql-test/r/mdl_sync.result 2010-09-08 08:25:37 +0000
+++ b/mysql-test/r/mdl_sync.result 2010-09-09 07:50:04 +0000
@@ -2951,3 +2951,47 @@ SET DEBUG_SYNC= 'now SIGNAL continue';
# Connection default
DROP TABLE m1, t1, t2;
SET DEBUG_SYNC= 'RESET';
+#
+# Bug#56494 Segfault in upgrade_shared_lock_to_exclusive() for
+# REPAIR of merge table
+#
+DROP TABLE IF EXISTS t1, t2, t_not_exists;
+CREATE TABLE t1(a INT);
+ALTER TABLE t1 engine= MERGE UNION (t_not_exists);
+ANALYZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 analyze Error Table 'test.t_not_exists' doesn't exist
+test.t1 analyze Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1 analyze error Corrupt
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check Error Table 'test.t_not_exists' doesn't exist
+test.t1 check Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1 check error Corrupt
+CHECKSUM TABLE t1;
+Table Checksum
+test.t1 NULL
+Warnings:
+Error 1146 Table 'test.t_not_exists' doesn't exist
+Error 1168 Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize Error Table 'test.t_not_exists' doesn't exist
+test.t1 optimize Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1 optimize error Corrupt
+REPAIR TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 repair Error Table 'test.t_not_exists' doesn't exist
+test.t1 repair Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1 repair error Corrupt
+REPAIR TABLE t1 USE_FRM;
+Table Op Msg_type Msg_text
+test.t1 repair Warning Can't open table
+test.t1 repair error Corrupt
+DROP TABLE t1;
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(a INT) engine= MERGE UNION (t1);
+REPAIR TABLE t2 USE_FRM;
+Table Op Msg_type Msg_text
+test.t2 repair note The storage engine for the table doesn't support repair
+DROP TABLE t1, t2;
=== modified file 'mysql-test/r/merge.result'
--- a/mysql-test/r/merge.result 2010-09-08 08:25:37 +0000
+++ b/mysql-test/r/merge.result 2010-09-09 07:50:04 +0000
@@ -2677,7 +2677,7 @@ OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize Error Table 'test.t_not_exists' doesn't exist
test.t1 optimize Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
-test.t1 optimize note The storage engine for the table doesn't support optimize
+test.t1 optimize error Corrupt
DROP TABLE t1;
#
# Bug#36171 - CREATE TEMPORARY TABLE and MERGE engine
=== modified file 'mysql-test/r/myisampack.result'
--- a/mysql-test/r/myisampack.result 2009-11-26 12:47:55 +0000
+++ b/mysql-test/r/myisampack.result 2010-09-09 07:50:04 +0000
@@ -46,14 +46,12 @@ insert into t1 select * from t1;
flush tables;
optimize table t1;
Table Op Msg_type Msg_text
-test.t1 optimize error Table 'test.t1' is read only
-Warnings:
-Error 1036 Table 't1' is read only
+test.t1 optimize Error Table 't1' is read only
+test.t1 optimize error Corrupt
repair table t1;
Table Op Msg_type Msg_text
-test.t1 repair error Table 'test.t1' is read only
-Warnings:
-Error 1036 Table 't1' is read only
+test.t1 repair Error Table 't1' is read only
+test.t1 repair error Corrupt
drop table t1;
#
# BUG#41541 - Valgrind warnings on packed MyISAM table
=== modified file 'mysql-test/r/mysql_upgrade.result'
--- a/mysql-test/r/mysql_upgrade.result 2010-07-05 10:22:13 +0000
+++ b/mysql-test/r/mysql_upgrade.result 2010-09-09 07:50:04 +0000
@@ -7,7 +7,7 @@ mysql.event
mysql.func OK
mysql.general_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.help_category OK
mysql.help_keyword OK
mysql.help_relation OK
@@ -20,7 +20,7 @@ mysql.procs_priv
mysql.servers OK
mysql.slow_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.tables_priv OK
mysql.time_zone OK
mysql.time_zone_leap_second OK
@@ -28,6 +28,10 @@ mysql.time_zone_name
mysql.time_zone_transition OK
mysql.time_zone_transition_type OK
mysql.user OK
+
+Repairing tables
+mysql.general_log OK
+mysql.slow_log OK
Run it again - should say already completed
This installation of MySQL is already upgraded to VERSION, use --force if you still need to run mysql_upgrade
Force should run it regardless of wether it's been run before
@@ -39,7 +43,7 @@ mysql.event
mysql.func OK
mysql.general_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.help_category OK
mysql.help_keyword OK
mysql.help_relation OK
@@ -52,7 +56,7 @@ mysql.procs_priv
mysql.servers OK
mysql.slow_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.tables_priv OK
mysql.time_zone OK
mysql.time_zone_leap_second OK
@@ -60,6 +64,10 @@ mysql.time_zone_name
mysql.time_zone_transition OK
mysql.time_zone_transition_type OK
mysql.user OK
+
+Repairing tables
+mysql.general_log OK
+mysql.slow_log OK
CREATE USER mysqltest1@'%' IDENTIFIED by 'sakila';
GRANT ALL ON *.* TO mysqltest1@'%';
Run mysql_upgrade with password protected account
@@ -71,7 +79,7 @@ mysql.event
mysql.func OK
mysql.general_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.help_category OK
mysql.help_keyword OK
mysql.help_relation OK
@@ -84,7 +92,7 @@ mysql.procs_priv
mysql.servers OK
mysql.slow_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.tables_priv OK
mysql.time_zone OK
mysql.time_zone_leap_second OK
@@ -92,6 +100,10 @@ mysql.time_zone_name
mysql.time_zone_transition OK
mysql.time_zone_transition_type OK
mysql.user OK
+
+Repairing tables
+mysql.general_log OK
+mysql.slow_log OK
DROP USER mysqltest1@'%';
Run mysql_upgrade with a non existing server socket
mysqlcheck: Got error: 2005: Unknown MySQL server host 'not_existing_host' (errno) when trying to connect
@@ -105,7 +117,7 @@ mysql.event
mysql.func OK
mysql.general_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.help_category OK
mysql.help_keyword OK
mysql.help_relation OK
@@ -118,7 +130,7 @@ mysql.procs_priv
mysql.servers OK
mysql.slow_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.tables_priv OK
mysql.time_zone OK
mysql.time_zone_leap_second OK
@@ -126,6 +138,10 @@ mysql.time_zone_name
mysql.time_zone_transition OK
mysql.time_zone_transition_type OK
mysql.user OK
+
+Repairing tables
+mysql.general_log OK
+mysql.slow_log OK
set GLOBAL sql_mode=default;
#
# Bug #41569 mysql_upgrade (ver 5.1) add 3 fields to mysql.proc table
@@ -143,7 +159,7 @@ mysql.event
mysql.func OK
mysql.general_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.help_category OK
mysql.help_keyword OK
mysql.help_relation OK
@@ -156,7 +172,7 @@ mysql.procs_priv
mysql.servers OK
mysql.slow_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.tables_priv OK
mysql.time_zone OK
mysql.time_zone_leap_second OK
@@ -164,6 +180,10 @@ mysql.time_zone_name
mysql.time_zone_transition OK
mysql.time_zone_transition_type OK
mysql.user OK
+
+Repairing tables
+mysql.general_log OK
+mysql.slow_log OK
CALL testproc();
DROP PROCEDURE testproc;
WARNING: NULL values of the 'character_set_client' column ('mysql.proc' table) have been updated with a default value (latin1). Please verify if necessary.
@@ -184,7 +204,7 @@ mysql.event
mysql.func OK
mysql.general_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.help_category OK
mysql.help_keyword OK
mysql.help_relation OK
@@ -197,7 +217,7 @@ mysql.procs_priv
mysql.servers OK
mysql.slow_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.tables_priv OK
mysql.time_zone OK
mysql.time_zone_leap_second OK
@@ -205,6 +225,10 @@ mysql.time_zone_name
mysql.time_zone_transition OK
mysql.time_zone_transition_type OK
mysql.user OK
+
+Repairing tables
+mysql.general_log OK
+mysql.slow_log OK
SHOW GRANTS FOR 'user3'@'%';
Grants for user3@%
GRANT USAGE ON *.* TO 'user3'@'%'
=== modified file 'mysql-test/r/mysql_upgrade_ssl.result'
--- a/mysql-test/r/mysql_upgrade_ssl.result 2010-08-11 17:56:56 +0000
+++ b/mysql-test/r/mysql_upgrade_ssl.result 2010-09-09 07:50:04 +0000
@@ -9,7 +9,7 @@ mysql.event
mysql.func OK
mysql.general_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.help_category OK
mysql.help_keyword OK
mysql.help_relation OK
@@ -22,7 +22,7 @@ mysql.procs_priv
mysql.servers OK
mysql.slow_log
Error : You can't use locks with log tables.
-status : OK
+error : Corrupt
mysql.tables_priv OK
mysql.time_zone OK
mysql.time_zone_leap_second OK
@@ -30,3 +30,7 @@ mysql.time_zone_name
mysql.time_zone_transition OK
mysql.time_zone_transition_type OK
mysql.user OK
+
+Repairing tables
+mysql.general_log OK
+mysql.slow_log OK
=== modified file 'mysql-test/t/mdl_sync.test'
--- a/mysql-test/t/mdl_sync.test 2010-09-08 08:25:37 +0000
+++ b/mysql-test/t/mdl_sync.test 2010-09-09 07:50:04 +0000
@@ -4594,6 +4594,36 @@ disconnect con1;
disconnect con2;
+--echo #
+--echo # Bug#56494 Segfault in upgrade_shared_lock_to_exclusive() for
+--echo # REPAIR of merge table
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2, t_not_exists;
+--enable_warnings
+
+CREATE TABLE t1(a INT);
+ALTER TABLE t1 engine= MERGE UNION (t_not_exists);
+# This caused the segfault
+ANALYZE TABLE t1;
+CHECK TABLE t1;
+CHECKSUM TABLE t1;
+OPTIMIZE TABLE t1;
+REPAIR TABLE t1;
+
+# This caused an assert
+REPAIR TABLE t1 USE_FRM;
+
+DROP TABLE t1;
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(a INT) engine= MERGE UNION (t1);
+# This caused an assert
+REPAIR TABLE t2 USE_FRM;
+
+DROP TABLE t1, t2;
+
+
# Check that all connections opened by test cases in this file are really
# gone so execution of other tests won't be affected by their presence.
--source include/wait_until_count_sessions.inc
=== modified file 'sql/sql_admin.cc'
--- a/sql/sql_admin.cc 2010-08-18 11:29:04 +0000
+++ b/sql/sql_admin.cc 2010-09-09 07:50:04 +0000
@@ -112,7 +112,8 @@ static int prepare_for_repair(THD *thd,
}
/* A MERGE table must not come here. */
- DBUG_ASSERT(table->file->ht->db_type != DB_TYPE_MRG_MYISAM);
+ if (table->file->ht->db_type == DB_TYPE_MRG_MYISAM)
+ goto end;
/*
REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
@@ -320,6 +321,14 @@ static bool mysql_admin_table(THD* thd,
table->next_global= save_next_global;
table->next_local= save_next_local;
thd->open_options&= ~extra_open_options;
+
+ /*
+ If open_and_lock_tables() failed, close_thread_tables() will close
+ the table and table->table can therefore be invalid.
+ */
+ if (open_error)
+ table->table= NULL;
+
/*
Under locked tables, we know that the table can be opened,
so any errors opening the table are logical errors.
Attachment: [text/bzr-bundle] bzr/jon.hauglid@oracle.com-20100909075004-qpouhrstqjwk05c0.bundle
| Thread |
|---|
| • bzr commit into mysql-5.5-runtime branch (jon.hauglid:3134) Bug#56494 | Jon Olav Hauglid | 9 Sep |