summaryrefslogtreecommitdiff
path: root/sql/lock.cc
diff options
context:
space:
mode:
authordlenev@mockturtle.local <>2006-08-21 19:02:11 +0400
committerdlenev@mockturtle.local <>2006-08-21 19:02:11 +0400
commit8fb55ff0cfd891334fc4411763065e827339222f (patch)
tree3ff756469c7140c8df00e77b9d805a46ea37c21e /sql/lock.cc
parenta486f955474e4414b6a16f98968a196803b5c63e (diff)
downloadmariadb-git-8fb55ff0cfd891334fc4411763065e827339222f.tar.gz
Fix for bug#19403/12212 "Crash that happens during removing of database name
from cache" and #21216 "Simultaneous DROP TABLE and SHOW OPEN TABLES causes server to crash". Crash happened when one ran DROP DATABASE or SHOW OPEN TABLES statements while concurrently doing DROP TABLE (or RENAME TABLE, CREATE TABLE LIKE or any other command that takes name-lock) in other connection. This problem was caused by the fact that table placeholders which were added to table cache in order to obtain name-lock on table had TABLE_SHARE::db and table_name set to 0. Therefore they broke assumption that these members are non-0 for all tables in table cache on which some of our code relies. The fix sets these members for such placeholders to appropriate value making this assumption true again. As attempt to avoid such problems in future we introduce auxiliary TABLE_SHARE::set_table_cache_key() methods which should be used when one wants to set TABLE_SHARE::table_cache_key and which ensure that TABLE_SHARE::table_name/db are set properly. Test cases for these bugs were added to 5.0 test-suite (with 5.0-specific fix for bug #21216).
Diffstat (limited to 'sql/lock.cc')
-rw-r--r--sql/lock.cc21
1 files changed, 12 insertions, 9 deletions
diff --git a/sql/lock.cc b/sql/lock.cc
index 8e75ea42f7d..06f538a2a03 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -874,6 +874,8 @@ end:
int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use)
{
TABLE *table;
+ TABLE_SHARE *share;
+ char *key_buff;
char key[MAX_DBKEY_LENGTH];
char *db= table_list->db;
uint key_length;
@@ -903,17 +905,18 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use)
}
/*
Create a table entry with the right key and with an old refresh version
- Note that we must use my_malloc() here as this is freed by the table
- cache
+ Note that we must use my_multi_malloc() here as this is freed by the
+ table cache
*/
- if (!(table= (TABLE*) my_malloc(sizeof(*table)+ sizeof(TABLE_SHARE)+
- key_length, MYF(MY_WME | MY_ZEROFILL))))
+ if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
+ &table, sizeof(*table),
+ &share, sizeof(*share),
+ &key_buff, key_length,
+ NULL))
DBUG_RETURN(-1);
- table->s= (TABLE_SHARE*) (table+1);
- memcpy((table->s->table_cache_key.str= (char*) (table->s+1)), key,
- key_length);
- table->s->table_cache_key.length= key_length;
- table->s->tmp_table= INTERNAL_TMP_TABLE; // for intern_close_table
+ table->s= share;
+ share->set_table_cache_key(key_buff, key, key_length);
+ share->tmp_table= INTERNAL_TMP_TABLE; // for intern_close_table
table->in_use= thd;
table->locked_by_name=1;
table_list->table=table;