summaryrefslogtreecommitdiff
path: root/sql/sql_handler.cc
diff options
context:
space:
mode:
authorunknown <davi@moksha.local>2007-08-17 11:34:12 -0300
committerunknown <davi@moksha.local>2007-08-17 11:34:12 -0300
commit8bdb043f087ffbad27ab6daaeba8954b41711b57 (patch)
tree74929bc92e9f78a68ece540e3c2f9161d5b9dd9e /sql/sql_handler.cc
parentd811750fe890293970be9cd8d7b73258dd280da5 (diff)
downloadmariadb-git-8bdb043f087ffbad27ab6daaeba8954b41711b57.tar.gz
Bug#25856 (HANDLER table OPEN in one connection lock DROP TABLE in another one)
mysql_ha_open calls mysql_ha_close on the error path (unsupported) to close the (opened) table before inserting it into the tables hash list handler_tables_hash) but mysql_ha_close only closes tables which are on the hash list, causing the table to be left open and locked. This change moves the table close logic into a separate function that is always called on the error path of mysql_ha_open or on a normal handler close (mysql_ha_close). mysql-test/r/lock_multi.result: Bug#25856 test result mysql-test/t/lock_multi.test: Bug#25856 test case sql/sql_handler.cc: Move the table close logic into a separate function that is always called on the error path of mysql_ha_open or on a normal handler close.
Diffstat (limited to 'sql/sql_handler.cc')
-rw-r--r--sql/sql_handler.cc80
1 files changed, 47 insertions, 33 deletions
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 300ec7f3c62..eaa0da06630 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -119,6 +119,44 @@ static void mysql_ha_hash_free(TABLE_LIST *tables)
my_free((char*) tables, MYF(0));
}
+/**
+ Close a HANDLER table.
+
+ @param thd Thread identifier.
+ @param tables A list of tables with the first entry to close.
+
+ @note Though this function takes a list of tables, only the first list entry
+ will be closed.
+ @note Broadcasts refresh if it closed the table.
+*/
+
+static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables)
+{
+ TABLE **table_ptr;
+
+ /*
+ Though we could take the table pointer from hash_tables->table,
+ we must follow the thd->handler_tables chain anyway, as we need the
+ address of the 'next' pointer referencing this table
+ for close_thread_table().
+ */
+ for (table_ptr= &(thd->handler_tables);
+ *table_ptr && (*table_ptr != tables->table);
+ table_ptr= &(*table_ptr)->next)
+ ;
+
+ if (*table_ptr)
+ {
+ (*table_ptr)->file->ha_index_or_rnd_end();
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (close_thread_table(thd, table_ptr))
+ {
+ /* Tell threads waiting for refresh that something has happened */
+ broadcast_refresh();
+ }
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ }
+}
/*
Open a HANDLER table.
@@ -145,7 +183,7 @@ static void mysql_ha_hash_free(TABLE_LIST *tables)
bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
{
- TABLE_LIST *hash_tables;
+ TABLE_LIST *hash_tables = NULL;
char *db, *name, *alias;
uint dblen, namelen, aliaslen, counter;
int error;
@@ -197,7 +235,6 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
{
if (! reopen)
my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
- mysql_ha_close(thd, tables);
goto err;
}
@@ -225,11 +262,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
/* add to hash */
if (my_hash_insert(&thd->handler_tables_hash, (uchar*) hash_tables))
- {
- my_free((char*) hash_tables, MYF(0));
- mysql_ha_close(thd, tables);
goto err;
- }
}
if (! reopen)
@@ -238,13 +271,17 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
DBUG_RETURN(FALSE);
err:
+ if (hash_tables)
+ my_free((char*) hash_tables, MYF(0));
+ if (tables->table)
+ mysql_ha_close_table(thd, tables);
DBUG_PRINT("exit",("ERROR"));
DBUG_RETURN(TRUE);
}
/*
- Close a HANDLER table.
+ Close a HANDLER table by alias or table name
SYNOPSIS
mysql_ha_close()
@@ -252,9 +289,8 @@ err:
tables A list of tables with the first entry to close.
DESCRIPTION
- Though this function takes a list of tables, only the first list entry
- will be closed.
- Broadcasts refresh if it closed the table.
+ Closes the table that is associated (on the handler tables hash) with the
+ name (table->alias) of the specified table.
RETURN
FALSE ok
@@ -264,7 +300,6 @@ err:
bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
{
TABLE_LIST *hash_tables;
- TABLE **table_ptr;
DBUG_ENTER("mysql_ha_close");
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
tables->db, tables->table_name, tables->alias));
@@ -273,28 +308,7 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
(uchar*) tables->alias,
strlen(tables->alias) + 1)))
{
- /*
- Though we could take the table pointer from hash_tables->table,
- we must follow the thd->handler_tables chain anyway, as we need the
- address of the 'next' pointer referencing this table
- for close_thread_table().
- */
- for (table_ptr= &(thd->handler_tables);
- *table_ptr && (*table_ptr != hash_tables->table);
- table_ptr= &(*table_ptr)->next)
- ;
-
- if (*table_ptr)
- {
- (*table_ptr)->file->ha_index_or_rnd_end();
- VOID(pthread_mutex_lock(&LOCK_open));
- if (close_thread_table(thd, table_ptr))
- {
- /* Tell threads waiting for refresh that something has happened */
- broadcast_refresh();
- }
- VOID(pthread_mutex_unlock(&LOCK_open));
- }
+ mysql_ha_close_table(thd, hash_tables);
hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
}
else