summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
authorunknown <ingo@mysql.com>2005-11-15 21:57:02 +0100
committerunknown <ingo@mysql.com>2005-11-15 21:57:02 +0100
commit013b3d8ab33b052d504a2e3fa63a85c919c649cc (patch)
tree119cf106bff33787b0aad32bfaf568b654dd7115 /sql/sql_table.cc
parentd9c7aaf23ff30675682775864c269bde84a3bc03 (diff)
downloadmariadb-git-013b3d8ab33b052d504a2e3fa63a85c919c649cc.tar.gz
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc23
1 files changed, 14 insertions, 9 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index c0748abf333..0d6ef9bb767 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -103,23 +103,28 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
/* mark for close and remove all cached entries */
- thd->mysys_var->current_mutex= &LOCK_open;
- thd->mysys_var->current_cond= &COND_refresh;
- VOID(pthread_mutex_lock(&LOCK_open));
-
if (!drop_temporary)
{
if ((error= wait_if_global_read_lock(thd, 0, 1)))
{
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
- goto err;
+ DBUG_RETURN(TRUE);
}
else
need_start_waiters= TRUE;
}
+
+ /*
+ Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
+ LOCK_open during wait_if_global_read_lock(), other threads could not
+ close their tables. This would make a pretty deadlock.
+ */
+ thd->mysys_var->current_mutex= &LOCK_open;
+ thd->mysys_var->current_cond= &COND_refresh;
+ VOID(pthread_mutex_lock(&LOCK_open));
+
error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
-err:
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&thd->mysys_var->mutex);
@@ -232,7 +237,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
char *db=table->db;
db_type table_type= DB_TYPE_UNKNOWN;
- mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL);
+ mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE);
if (!close_temporary_table(thd, db, table->table_name))
{
tmp_table_deleted=1;
@@ -2171,7 +2176,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
- mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL);
+ mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, FALSE);
for (table= tables; table; table= table->next_local)
{
char table_name[NAME_LEN*2+2];
@@ -3128,7 +3133,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
new_db= db;
used_fields=create_info->used_fields;
- mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL);
+ mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,