From: Mattias Jonsson Date: December 11 2009 11:37am Subject: bzr commit into mysql-5.1-bugteam branch (mattias.jonsson:3238) Bug#42438 List-Archive: http://lists.mysql.com/commits/93669 X-Bug: 42438 Message-Id: <20091211113727.CBEDD2B3C6D4@client-10-129-10-236.upp.off.mysql.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_kgIOroBvSCs5mu7xCPmdAw)" --Boundary_(ID_kgIOroBvSCs5mu7xCPmdAw) MIME-version: 1.0 Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-disposition: inline #At file:///Users/mattiasj/clones/bzrroot/b42438-51-bt/ based on revid:bar@stripped 3238 Mattias Jonsson 2009-12-11 Bug#42438: Crash ha_partition::change_table_ptr There was two problems: The first was the symptom, caused by bad error handling in ha_partition. It did not handle print_error etc. when having no partitions (when used by dummy handler). The second was the real problem that when dropping tables it reused the table type (storage engine) from when the lock was asked for, not the table type that it had when gaining the exclusive name lock. So that it tried to delete tables from wrong storage engines. Solutions for the first problem was to accept some handler calls to the partitioning handler even if it was not setup with any partitions, and also if possible fallback to use the base handler's default functions. Solution for the second problem was to re-read the current table type from the frm file, when under LOCK_open, just before deleting the tables from the storage engine. @ mysql-test/r/partition_debug_sync.result Bug#42438: Crash ha_partition::change_table_ptr New result file using DEBUG_SYNC for deterministic results. @ mysql-test/t/partition_debug_sync.test Bug#42438: Crash ha_partition::change_table_ptr New test file using DEBUG_SYNC for deterministic results. @ sql/ha_partition.cc Bug#42438: Crash ha_partition::change_table_ptr allow some handler calls, used by error handling, even when no partitions are setup. Fallback to default handling if possible. @ sql/sql_base.cc Bug#42438: Crash ha_partition::change_table_ptr Added DEBUG_SYNC point for deterministic test cases. @ sql/sql_table.cc Bug#42438: Crash ha_partition::change_table_ptr Always use the table type written in the .frm-file (i.e. the current table type) when deleting a table. Added DEBUG_SYNC points for deterministic test cases. added: mysql-test/r/partition_debug_sync.result mysql-test/t/partition_debug_sync.test modified: sql/ha_partition.cc sql/sql_base.cc sql/sql_table.cc === added file 'mysql-test/r/partition_debug_sync.result' --- a/mysql-test/r/partition_debug_sync.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/r/partition_debug_sync.result 2009-12-11 11:37:17 +0000 @@ -0,0 +1,57 @@ +DROP TABLE IF EXISTS t1, t2; +SET DEBUG_SYNC= 'RESET'; +# +# Bug#42438: Crash ha_partition::change_table_ptr +# Test when remove partitioning is done while drop table is waiting +# for the table. +# Con 1 +SET DEBUG_SYNC= 'RESET'; +CREATE TABLE t1 +(a INTEGER, +b INTEGER NOT NULL, +KEY (b)) +ENGINE = MYISAM +/*!50100 PARTITION BY RANGE (a) +(PARTITION p0 VALUES LESS THAN (2), +PARTITION p1 VALUES LESS THAN (20), +PARTITION p2 VALUES LESS THAN (100), +PARTITION p3 VALUES LESS THAN MAXVALUE ) */; +SET DEBUG_SYNC= 'alter_table_before_create_table_no_lock SIGNAL removing_partitioning WAIT_FOR waiting_for_alter'; +SET DEBUG_SYNC= 'alter_table_before_main_binlog SIGNAL partitioning_removed'; +ALTER TABLE t1 REMOVE PARTITIONING; +# Con default +SET DEBUG_SYNC= 'now WAIT_FOR removing_partitioning'; +SET DEBUG_SYNC= 'waiting_for_table SIGNAL waiting_for_alter'; +SET DEBUG_SYNC= 'rm_table_part2_before_delete_table WAIT_FOR partitioning_removed'; +DROP TABLE IF EXISTS t1; +# Con 1 +SET DEBUG_SYNC= 'RESET'; +SET DEBUG_SYNC= 'RESET'; +# +# Bug#42438: Crash ha_partition::change_table_ptr +# Test when remove partitioning is failing due to drop table is already +# in progress. +CREATE TABLE t2 +(a INTEGER, +b INTEGER NOT NULL, +KEY (b)) +ENGINE = MYISAM +/*!50100 PARTITION BY RANGE (a) +(PARTITION p0 VALUES LESS THAN (2), +PARTITION p1 VALUES LESS THAN (20), +PARTITION p2 VALUES LESS THAN (100), +PARTITION p3 VALUES LESS THAN MAXVALUE ) */; +SET DEBUG_SYNC= 'before_lock_tables_takes_lock SIGNAL removing_partitions WAIT_FOR waiting_for_alter'; +SET DEBUG_SYNC= 'alter_table_before_rename_result_table WAIT_FOR delete_done'; +ALTER TABLE t2 REMOVE PARTITIONING; +# Con default +SET DEBUG_SYNC= 'now WAIT_FOR removing_partitions'; +SET DEBUG_SYNC= 'waiting_for_table SIGNAL waiting_for_alter'; +SET DEBUG_SYNC= 'rm_table_part2_before_binlog SIGNAL delete_done'; +DROP TABLE IF EXISTS t2; +# Con 1 +ERROR 42S02: Table 'test.t2' doesn't exist +SET DEBUG_SYNC= 'RESET'; +# Con default +SET DEBUG_SYNC= 'RESET'; +End of 5.1 tests === added file 'mysql-test/t/partition_debug_sync.test' --- a/mysql-test/t/partition_debug_sync.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/t/partition_debug_sync.test 2009-12-11 11:37:17 +0000 @@ -0,0 +1,81 @@ +#--disable_abort_on_error +# +# Test for the partition storage engine which require DEBUG_SYNC feature to +# Created by Mattias Jonsson +# +--source include/have_partition.inc +--source include/have_debug_sync.inc + +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +SET DEBUG_SYNC= 'RESET'; +--enable_warnings + +--echo # +--echo # Bug#42438: Crash ha_partition::change_table_ptr +--echo # Test when remove partitioning is done while drop table is waiting +--echo # for the table. +connect(con1, localhost, root,,); +--echo # Con 1 +SET DEBUG_SYNC= 'RESET'; +CREATE TABLE t1 +(a INTEGER, + b INTEGER NOT NULL, + KEY (b)) +ENGINE = MYISAM +/*!50100 PARTITION BY RANGE (a) +(PARTITION p0 VALUES LESS THAN (2), + PARTITION p1 VALUES LESS THAN (20), + PARTITION p2 VALUES LESS THAN (100), + PARTITION p3 VALUES LESS THAN MAXVALUE ) */; +SET DEBUG_SYNC= 'alter_table_before_create_table_no_lock SIGNAL removing_partitioning WAIT_FOR waiting_for_alter'; +SET DEBUG_SYNC= 'alter_table_before_main_binlog SIGNAL partitioning_removed'; +--send ALTER TABLE t1 REMOVE PARTITIONING +connection default; +--echo # Con default +SET DEBUG_SYNC= 'now WAIT_FOR removing_partitioning'; +SET DEBUG_SYNC= 'waiting_for_table SIGNAL waiting_for_alter'; +SET DEBUG_SYNC= 'rm_table_part2_before_delete_table WAIT_FOR partitioning_removed'; +DROP TABLE IF EXISTS t1; +--echo # Con 1 +connection con1; +--reap +connection default; +SET DEBUG_SYNC= 'RESET'; +connection con1; +SET DEBUG_SYNC= 'RESET'; + +--echo # +--echo # Bug#42438: Crash ha_partition::change_table_ptr +--echo # Test when remove partitioning is failing due to drop table is already +--echo # in progress. +CREATE TABLE t2 +(a INTEGER, + b INTEGER NOT NULL, + KEY (b)) +ENGINE = MYISAM +/*!50100 PARTITION BY RANGE (a) +(PARTITION p0 VALUES LESS THAN (2), + PARTITION p1 VALUES LESS THAN (20), + PARTITION p2 VALUES LESS THAN (100), + PARTITION p3 VALUES LESS THAN MAXVALUE ) */; +SET DEBUG_SYNC= 'before_lock_tables_takes_lock SIGNAL removing_partitions WAIT_FOR waiting_for_alter'; +SET DEBUG_SYNC= 'alter_table_before_rename_result_table WAIT_FOR delete_done'; +--send ALTER TABLE t2 REMOVE PARTITIONING +connection default; +--echo # Con default +SET DEBUG_SYNC= 'now WAIT_FOR removing_partitions'; +SET DEBUG_SYNC= 'waiting_for_table SIGNAL waiting_for_alter'; +SET DEBUG_SYNC= 'rm_table_part2_before_binlog SIGNAL delete_done'; +DROP TABLE IF EXISTS t2; +--echo # Con 1 +connection con1; +--error ER_NO_SUCH_TABLE +--reap +SET DEBUG_SYNC= 'RESET'; +disconnect con1; +connection default; +--echo # Con default +SET DEBUG_SYNC= 'RESET'; + +--echo End of 5.1 tests === modified file 'sql/ha_partition.cc' --- a/sql/ha_partition.cc 2009-10-09 07:56:07 +0000 +++ b/sql/ha_partition.cc 2009-12-11 11:37:17 +0000 @@ -1719,13 +1719,19 @@ void ha_partition::update_create_info(HA void ha_partition::change_table_ptr(TABLE *table_arg, TABLE_SHARE *share) { - handler **file_array= m_file; + handler **file_array; table= table_arg; table_share= share; - do + if (m_file) { - (*file_array)->change_table_ptr(table_arg, share); - } while (*(++file_array)); + file_array= m_file; + DBUG_ASSERT(*file_array); + do + { + (*file_array)->change_table_ptr(table_arg, share); + } while (*(++file_array)); + } + if (m_added_file && m_added_file[0]) { /* if in middle of a drop/rename etc */ @@ -5986,7 +5992,12 @@ void ha_partition::print_error(int error if (error == HA_ERR_NO_PARTITION_FOUND) m_part_info->print_no_partition_found(table); else - m_file[m_last_part]->print_error(error, errflag); + { + if (m_file) + m_file[m_last_part]->print_error(error, errflag); + else + handler::print_error(error, errflag); + } DBUG_VOID_RETURN; } @@ -5996,7 +6007,10 @@ bool ha_partition::get_error_message(int DBUG_ENTER("ha_partition::get_error_message"); /* Should probably look for my own errors first */ - DBUG_RETURN(m_file[m_last_part]->get_error_message(error, buf)); + if (m_file) + DBUG_RETURN(m_file[m_last_part]->get_error_message(error, buf)); + DBUG_RETURN(handler::get_error_message(error, buf)); + } === modified file 'sql/sql_base.cc' --- a/sql/sql_base.cc 2009-11-20 20:56:43 +0000 +++ b/sql/sql_base.cc 2009-12-11 11:37:17 +0000 @@ -2165,6 +2165,7 @@ void wait_for_condition(THD *thd, pthrea proc_info=thd->proc_info; thd_proc_info(thd, "Waiting for table"); DBUG_ENTER("wait_for_condition"); + DEBUG_SYNC(thd, "waiting_for_table"); if (!thd->killed) (void) pthread_cond_wait(cond, mutex); === modified file 'sql/sql_table.cc' --- a/sql/sql_table.cc 2009-11-27 13:34:39 +0000 +++ b/sql/sql_table.cc 2009-12-11 11:37:17 +0000 @@ -22,6 +22,9 @@ #include "sp_head.h" #include "sql_trigger.h" #include "sql_show.h" +#if defined(ENABLED_DEBUG_SYNC) +#include "debug_sync.h" +#endif #ifdef __WIN__ #include @@ -1904,7 +1907,7 @@ int mysql_rm_table_part2(THD *thd, TABLE { char *db=table->db; handlerton *table_type; - enum legacy_db_type frm_db_type; + enum legacy_db_type frm_db_type= DB_TYPE_UNKNOWN; DBUG_PRINT("table", ("table_l: '%s'.'%s' table: 0x%lx s: 0x%lx", table->db, table->table_name, (long) table->table, @@ -1996,6 +1999,7 @@ int mysql_rm_table_part2(THD *thd, TABLE table->internal_tmp_table ? FN_IS_TMP : 0); } + DEBUG_SYNC(thd, "rm_table_part2_before_delete_table"); if (drop_temporary || ((table_type == NULL && access(path, F_OK) && @@ -2014,13 +2018,25 @@ int mysql_rm_table_part2(THD *thd, TABLE else { char *end; - if (table_type == NULL) + /* + Cannot use the db_type from the table, since that might have changed + while waiting for the exclusive name lock. We are under LOCK_open, + so reading from the frm-file is safe. + */ + if (frm_db_type == DB_TYPE_UNKNOWN) + { + mysql_frm_type(thd, path, &frm_db_type); + DBUG_PRINT("info", ("frm_db_type %d from %s", frm_db_type, path)); + } + if (table_type == NULL || table_type->db_type != frm_db_type) { - mysql_frm_type(thd, path, &frm_db_type); + DBUG_PRINT("info", ("table_type has changed during wait_for_condition," + " using type %d from .frm-file", frm_db_type)); table_type= ha_resolve_by_legacy_type(thd, frm_db_type); } // Remove extension for delete *(end= path + path_length - reg_ext_length)= '\0'; + DBUG_PRINT("info", ("deleting table of type %d", table_type->db_type)); error= ha_delete_table(thd, table_type, path, db, table->table_name, !dont_log_query); if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && @@ -2062,6 +2078,7 @@ int mysql_rm_table_part2(THD *thd, TABLE on the table name. */ pthread_mutex_unlock(&LOCK_open); + DEBUG_SYNC(thd, "rm_table_part2_before_binlog"); thd->thread_specific_used|= tmp_table_deleted; error= 0; if (wrong_tables.length()) @@ -7097,6 +7114,7 @@ view_err: else create_info->data_file_name=create_info->index_file_name=0; + DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock"); /* Create a table with a temporary name. With create_info->frm_only == 1 this creates a .frm file only. @@ -7296,6 +7314,7 @@ view_err: intern_close_table(new_table); my_free(new_table,MYF(0)); } + DEBUG_SYNC(thd, "alter_table_before_rename_result_table"); VOID(pthread_mutex_lock(&LOCK_open)); if (error) { @@ -7438,6 +7457,7 @@ view_err: thd_proc_info(thd, "end"); DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000);); + DEBUG_SYNC(thd, "alter_table_before_main_binlog"); ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE, thd->query(), thd->query_length(), --Boundary_(ID_kgIOroBvSCs5mu7xCPmdAw) MIME-version: 1.0 Content-type: text/bzr-bundle; CHARSET=US-ASCII; name*0="bzr/mattias.jonsson@stripped"; name*1=17-yhha6zzr2b13yg98.bundle Content-transfer-encoding: 7BIT Content-disposition: inline; filename*0="bzr/mattias.jonsson@stripped"; filename*1=17-yhha6zzr2b13yg98.bundle # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: mattias.jonsson@stripped # target_branch: file:///Users/mattiasj/clones/bzrroot/b42438-51-bt/ # testament_sha1: c808c63102514c8f49966f462ab746509b3e1cff # timestamp: 2009-12-11 12:37:27 +0100 # base_revision_id: bar@stripped # # Begin bundle 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 --Boundary_(ID_kgIOroBvSCs5mu7xCPmdAw)--