summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <guilhem@mysql.com>2003-09-26 22:57:34 +0200
committerunknown <guilhem@mysql.com>2003-09-26 22:57:34 +0200
commita4f7ed563f68b1fbdc84a897db46777b394740d7 (patch)
tree159b319b601dd12ea9fbf63c0aa512c647378325 /sql
parentf755cb36d032307af4a8863dbd7321d5032bf118 (diff)
parent44f65c246d80de4518e8d74359159b14a1ef3bd4 (diff)
downloadmariadb-git-a4f7ed563f68b1fbdc84a897db46777b394740d7.tar.gz
Merge gbichot@213.136.52.20:/home/bk/mysql-4.1
into mysql.com:/home/mysql_src/mysql-4.1
Diffstat (limited to 'sql')
-rw-r--r--sql/log_event.cc11
-rw-r--r--sql/sql_db.cc26
2 files changed, 31 insertions, 6 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc
index eee5be4c40f..b6964c40422 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1876,19 +1876,22 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
pthread_mutex_lock(&rli->data_lock);
-#ifdef TO_BE_CHECKED_BY_GUILHEM
- if (rli->inside_transaction)
+ if (thd->options & OPTION_BEGIN)
{
slave_print_error(rli, 0,
+ opt_using_transactions ?
"\
There is an unfinished transaction in the relay log (could find neither \
COMMIT nor ROLLBACK in the relay log); It could be that the master died while \
writing the transaction to its binary log. Now the slave is rolling back the \
-transaction.");
+transaction." :
+ "\
+There is an unfinished transaction in the relay log (could find neither \
+COMMIT nor ROLLBACK in the relay log); It could be that the master died while \
+writing the transaction to its binary log.");
pthread_mutex_unlock(&rli->data_lock);
DBUG_RETURN(1);
}
-#endif
memcpy(log_name, new_log_ident, ident_len+1);
rli->notify_group_master_log_name_update();
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 2b42c2c9a5b..2ba7f73ba80 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -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ż'"
+ - 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));