From: Li-Bing.Song Date: January 22 2010 2:59pm Subject: bzr commit into mysql-5.1-rep-semisync branch (Li-Bing.Song:3128) Bug#50157 List-Archive: http://lists.mysql.com/commits/97891 X-Bug: 50157 Message-Id: <201001221500.o0MF0DNX021629@anders-server> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============9077462256457831005==" --===============9077462256457831005== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/anders/work/bzrroot/mysql-5.1-rep-semisync/ based on revid:li-bing.song@stripped 3128 Li-Bing.Song@stripped 2010-01-22 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 created when each time some log events are written into binlog file and is synchronized. TranxNodes' memories are allocted from mem_root of the current thread, and will be freed immediately after current statement ending. from TranxNode list. So the Pointer of the TranxNode in TranxNode list becomes a wild pointer. After this patch, TranxNodes are not allocated from mem_root. added: plugin/semisync/semisync_node_allocator.h modified: mysql-test/suite/rpl/r/rpl_semi_sync_mixed_tables.result mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables.test plugin/semisync/semisync_master.cc plugin/semisync/semisync_master.h plugin/semisync/semisync_master_plugin.cc === modified file 'mysql-test/suite/rpl/r/rpl_semi_sync_mixed_tables.result' --- a/mysql-test/suite/rpl/r/rpl_semi_sync_mixed_tables.result 2010-01-20 08:37:18 +0000 +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_mixed_tables.result 2010-01-22 14:59:03 +0000 @@ -15,22 +15,26 @@ CREATE TABLE t2(c1 INT) ENGINE=innodb; call mtr.add_suppression(".*"); INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; SET GLOBAL rpl_semi_sync_master_enabled = 1; -SET GLOBAL rpl_semi_sync_master_trace_level= 80; +SET GLOBAL rpl_semi_sync_master_trace_level= 0; STOP SLAVE; INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; SET GLOBAL rpl_semi_sync_slave_enabled = 1; +SET GLOBAL rpl_semi_sync_slave_trace_level= 0; START SLAVE; BEGIN; # Even though it is in a transaction, this statement is binlogged into binlog # file immediately. -CREATE TEMPORARY TABLE t1 LIKE t2; +CREATE TEMPORARY TABLE t1 SELECT c1 FROM t2 where 1=1; +CREATE TEMPORARY TABLE t3 (c1 INT); # These statements will not binlogged until the transaction is committed INSERT INTO t2 VALUES(11); INSERT INTO t2 VALUES(22); COMMIT; +SET GLOBAL rpl_semi_sync_slave_enabled = 0; UNINSTALL PLUGIN rpl_semi_sync_slave; +SET GLOBAL rpl_semi_sync_master_enabled = 0; UNINSTALL PLUGIN rpl_semi_sync_master; -DROP TABLE t1, t2; +DROP TABLE t2; === modified file 'mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables.test' --- a/mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables.test 2010-01-20 08:37:18 +0000 +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_mixed_tables.test 2010-01-22 14:59:03 +0000 @@ -19,7 +19,7 @@ connection master; call mtr.add_suppression(".*"); eval INSTALL PLUGIN rpl_semi_sync_master SONAME '$SEMISYNC_MASTER_PLUGIN'; SET GLOBAL rpl_semi_sync_master_enabled = 1; -SET GLOBAL rpl_semi_sync_master_trace_level= 80; +SET GLOBAL rpl_semi_sync_master_trace_level= 0; connection slave; STOP SLAVE; @@ -27,6 +27,7 @@ source include/wait_for_slave_to_stop.in eval INSTALL PLUGIN rpl_semi_sync_slave SONAME '$SEMISYNC_SLAVE_PLUGIN'; SET GLOBAL rpl_semi_sync_slave_enabled = 1; +SET GLOBAL rpl_semi_sync_slave_trace_level= 0; START SLAVE; source include/wait_for_slave_to_start.inc; @@ -37,6 +38,7 @@ BEGIN; --echo # Even though it is in a transaction, this statement is binlogged into binlog --echo # file immediately. CREATE TEMPORARY TABLE t1 SELECT c1 FROM t2 where 1=1; +CREATE TEMPORARY TABLE t3 (c1 INT); --echo --echo # These statements will not binlogged until the transaction is committed INSERT INTO t2 VALUES(11); @@ -45,9 +47,12 @@ COMMIT; sync_slave_with_master; --echo + +SET GLOBAL rpl_semi_sync_slave_enabled = 0; UNINSTALL PLUGIN rpl_semi_sync_slave; connection master; +SET GLOBAL rpl_semi_sync_master_enabled = 0; UNINSTALL PLUGIN rpl_semi_sync_master; -DROP TABLE t1, t2; +DROP TABLE t2; source include/master-slave-end.inc; === modified file 'plugin/semisync/semisync_master.cc' --- a/plugin/semisync/semisync_master.cc 2009-12-04 05:43:38 +0000 +++ b/plugin/semisync/semisync_master.cc 2010-01-22 14:59:03 +0000 @@ -65,7 +65,7 @@ static int gettimeofday(struct timeval * ActiveTranx::ActiveTranx(pthread_mutex_t *lock, unsigned long trace_level) - : Trace(trace_level), + : Trace(trace_level), allocator_(max_connections), num_entries_(max_connections << 1), /* Transaction hash table size * is set to double the size * of max_connections */ @@ -123,7 +123,7 @@ ActiveTranx::TranxNode* ActiveTranx::all ha_autocommit_or_rollback() will always be called before that, so we are sure that the node will be removed from the active list before it get freed. */ - TranxNode *trx_node = (TranxNode *)thd_alloc(thd, sizeof(TranxNode)); + TranxNode *trx_node = allocator_.add_node(); if (trx_node) { trx_node->log_name_[0] = '\0'; @@ -271,6 +271,7 @@ int ActiveTranx::clear_active_tranx_node /* Clear the hash table. */ memset(trx_htb_, 0, num_entries_ * sizeof(TranxNode *)); + allocator_.delete_all_nodes(); /* Clear the active transaction list. */ if (trx_front_ != NULL) @@ -311,6 +312,7 @@ int ActiveTranx::clear_active_tranx_node } trx_front_ = new_front; + allocator_.delete_node_before(trx_front_); if (trace_level_ & kTraceDetail) sql_print_information("%s: cleared %d nodes back until pos (%s, %lu)", === modified file 'plugin/semisync/semisync_master.h' --- a/plugin/semisync/semisync_master.h 2009-12-04 01:46:33 +0000 +++ b/plugin/semisync/semisync_master.h 2010-01-22 14:59:03 +0000 @@ -19,6 +19,7 @@ #define SEMISYNC_MASTER_H #include "semisync.h" +#include "semisync_node_allocator.h" /** This class manages memory for active transaction list. @@ -38,6 +39,7 @@ private: struct TranxNode *hash_next_; /* the next node during hash collision */ }; + NodeAllocator allocator_; /* These two record the active transaction list in sort order. */ TranxNode *trx_front_, *trx_rear_; === modified file 'plugin/semisync/semisync_master_plugin.cc' --- a/plugin/semisync/semisync_master_plugin.cc 2010-01-20 08:37:18 +0000 +++ b/plugin/semisync/semisync_master_plugin.cc 2010-01-22 14:59:03 +0000 @@ -46,7 +46,10 @@ int repl_semi_request_commit(Trans_param int repl_semi_report_commit(Trans_param *param) { - if (param->log_pos) + + bool is_real_trans= param->flags & TRANS_IS_REAL_TRANS; + + if (is_real_trans && param->log_pos) { const char *binlog_name= param->log_file; return repl_semisync.commitTrx(binlog_name, param->log_pos); === added file 'plugin/semisync/semisync_node_allocator.h' --- a/plugin/semisync/semisync_node_allocator.h 1970-01-01 00:00:00 +0000 +++ b/plugin/semisync/semisync_node_allocator.h 2010-01-22 14:59:03 +0000 @@ -0,0 +1,174 @@ +/* Copyright (C) 2010 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef SEMISYNC_NODE_ALLOCATOR +#define SEMISYNC_NODE_ALLOCATOR + +/* + */ +template class NodeAllocator +{ +public: + /* init_nodes_ means how many nodes(class T) are in one block */ + NodeAllocator(uint init_nodes) : + init_nodes_(init_nodes), block_size_(init_nodes * sizeof(T)), + last_node_(0), head_(0), rear_(0), current_block_(0), block_num_(0) {} + + ~NodeAllocator() + { + Block *block= head_; + while (block != NULL) + { + Block *next= block->next; + free_block(block); + block= next; + } + } + + /* + Return a node pointer which follows the last_node_ immediately. + */ + T *add_node() + { + /* A block is allocated first, if there is no any block existing */ + if (block_num_ == 0 && allocate_block()) + return NULL; + + last_node_+= sizeof(T); + if (last_node_ == current_block_->end) + { + current_block_= current_block_->next; + /* All blocks are in use, so a new block is allocated */ + if (current_block_ == NULL && allocate_block()) + { + /* Recovery the last_node_ if allocate_block() fails */ + last_node_-= sizeof(T); + return NULL; + } + else + last_node_= current_block_->begin; + } + return static_cast(last_node_); + } + + int delete_all_nodes() + { + last_node_= head_ ? head_->begin : NULL; + //free_blocks(); + return 0; + } + + int delete_node_before(T* node) + { + Block *block; + Block *prev_block; + + assert(node != NULL); + block= head_; + while (block != current_block_->next) + { + void *p = static_cast(node); + if (block->begin <= p and block->end > p) + { + if (head_ != block) + { + rear_->next= head_; + head_= block; + rear_= prev_block; + rear_->next= NULL; + //free_blocks(); + } + return 0; + } + prev_block= block; + block= block->next; + } + return 1; + } + +private: + uint init_nodes_; + uint block_size_; + void* last_node_; + + struct Block { + void *begin; + void *end; + Block *next; + }; + Block *head_; + Block *rear_; + Block *current_block_; + uint block_num_; + + int allocate_block() + { + Block *block= (Block *)my_malloc(sizeof(Block), MYF(0)); + if (block) + { + block->begin= my_malloc(block_size_, MYF(0)); + if (block->begin) + { + block->end= block->begin + block_size_; + block->next= NULL; + + if (head_ == NULL) + head_= block; + else + rear_->next= block; + + /* New block always is put at the rear */ + rear_= block; + /* New block always is the current_block_ */ + current_block_= block; + last_node_= block->begin; + ++block_num_; + return 0; + } + else + my_free(block, MYF(0)); + } + return 1; + } + + void free_block(Block *block) + { + assert(block != NULL || block->begin != NULL); + my_free(block->begin, MYF(0)); + my_free(block, MYF(0)); + --block_num_; + } + + /* + */ + void free_blocks() + { + if (current_block_ == NULL) + return; + + Block *block= current_block_->next; + while (block_num_ > 3 && block != NULL) + { + Block *next= block->next; + free_block(block); + block= next; + } + current_block_->next= block; + if (block == NULL) + rear_= NULL; + } +}; + +#endif --===============9077462256457831005== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/li-bing.song@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: li-bing.song@stripped # target_branch: file:///home/anders/work/bzrroot/mysql-5.1-rep-\ # semisync/ # testament_sha1: 87feda51280680f36fea017993210a33588d2aeb # timestamp: 2010-01-22 22:59:13 +0800 # base_revision_id: li-bing.song@stripped\ # c0yr5tnjwyq7qcwg # # Begin bundle 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 BO7md7FE/5YBBIMbBT/xdyRThQkKMCZgIA== --===============9077462256457831005==--