diff options
author | unknown <davi@moksha.local> | 2007-08-17 11:34:12 -0300 |
---|---|---|
committer | unknown <davi@moksha.local> | 2007-08-17 11:34:12 -0300 |
commit | 8bdb043f087ffbad27ab6daaeba8954b41711b57 (patch) | |
tree | 74929bc92e9f78a68ece540e3c2f9161d5b9dd9e /sql/sql_handler.cc | |
parent | d811750fe890293970be9cd8d7b73258dd280da5 (diff) | |
download | mariadb-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.cc | 80 |
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 |