summaryrefslogtreecommitdiff
path: root/sql/rpl_handler.cc
diff options
context:
space:
mode:
authorunknown <Li-Bing.Song@sun.com>2010-01-31 02:26:51 +0800
committerunknown <Li-Bing.Song@sun.com>2010-01-31 02:26:51 +0800
commita1bfae20cb3e9cc8919bf4902865314d1bf9d6f7 (patch)
tree902fa38e040c6a851a7c4eb20ca0aeac07d77c6a /sql/rpl_handler.cc
parent5f71056f0ef585bd1a36adabf50e20ec65c07d15 (diff)
downloadmariadb-git-a1bfae20cb3e9cc8919bf4902865314d1bf9d6f7.tar.gz
BUG#50157 Assertion !active_tranxs_->is_tranx_end_pos(..) in ReplSemiSyncMaster::commitTrx
The root cause of the crash is that a TranxNode is freed before it is used. A TranxNode is allocated and inserted into the active list each time a log event is written and flushed into the binlog file. The memory for TranxNode is allocated with thd_alloc and will be freed at the end of the statement. The after_commit/after_rollback callback was supposed to be called before the end of each statement and remove the node from the active list. However this assumption is not correct in all cases(e.g. call 'CREATE TEMPORARY TABLE myisam_t SELECT * FROM innodb_t' in a transaction and delete all temporary tables automatically when a session closed), and can cause the memory allocated for TranxNode be freed before it was removed from the active list. So The TranxNode pointer in the active list would become a wild pointer and cause the crash. After this patch, We have a class called a TranxNodeAllocate which manages the memory for allocating and freeing TranxNode. It uses my_malloc to allocate memory. sql/rpl_handler.cc: params are not initialized.
Diffstat (limited to 'sql/rpl_handler.cc')
-rw-r--r--sql/rpl_handler.cc10
1 files changed, 5 insertions, 5 deletions
diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc
index c4b55e3d068..b347b7c751d 100644
--- a/sql/rpl_handler.cc
+++ b/sql/rpl_handler.cc
@@ -190,8 +190,8 @@ int Trans_delegate::after_commit(THD *thd, bool all)
{
Trans_param param;
bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
- if (is_real_trans)
- param.flags |= TRANS_IS_REAL_TRANS;
+
+ param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0;
Trans_binlog_info *log_info=
my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
@@ -218,8 +218,8 @@ int Trans_delegate::after_rollback(THD *thd, bool all)
{
Trans_param param;
bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
- if (is_real_trans)
- param.flags |= TRANS_IS_REAL_TRANS;
+
+ param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0;
Trans_binlog_info *log_info=
my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
@@ -228,7 +228,7 @@ int Trans_delegate::after_rollback(THD *thd, bool all)
param.log_pos= log_info ? log_info->log_pos : 0;
int ret= 0;
- FOREACH_OBSERVER(ret, after_commit, thd, (&param));
+ FOREACH_OBSERVER(ret, after_rollback, thd, (&param));
/*
This is the end of a real transaction or autocommit statement, we