1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

Merge abotchkov@bk-internal.mysql.com:/home/bk/mysql-4.1

into deer.(none):/home/hf/work/mysql-4.1.stmt
This commit is contained in:
hf@deer.(none)
2003-09-29 12:27:39 +05:00
6 changed files with 45 additions and 17 deletions

View File

@ -391,10 +391,32 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
exit:
start_waiting_global_read_lock(thd);
/*
If this database was the client's selected database, we silently change the
client's selected database to nothing (to have an empty SELECT DATABASE() in
the future). For this we free() thd->db and set it to 0. But we don't do
free() for the slave thread. Indeed, doing a x_free() on it leads to nasty
problems (i.e. long painful debugging) because in this thread, thd->db is
the same as data_buf and db of the Query_log_event which is dropping the
database. So if you free() thd->db, you're freeing data_buf. You set thd->db
to 0 but not data_buf (thd->db and data_buf are two distinct pointers which
point to the same place). Then in ~Query_log_event(), we have
'if (data_buf) free(data_buf)'
data_buf is !=0 so this makes a DOUBLE free().
Side effects of this double free() are, randomly (depends on the machine),
when the slave is replicating a DROP DATABASE:
- garbage characters in the error message:
"Error 'Can't drop database 'test2'; database doesn't exist' on query
'h4zI<7A>'"
- segfault
- hang in "free(vio)" (yes!) in the I/O or SQL slave threads (so slave
server hangs at shutdown etc).
*/
if (thd->db && !strcmp(thd->db, db))
{
x_free(thd->db);
thd->db= 0;
if (!(thd->slave_thread)) /* a slave thread will free it itself */
x_free(thd->db);
thd->db= 0;
}
exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));