| Bug #41835 | Falcon crash in Table::getSyncPrior | ||
|---|---|---|---|
| Submitted: | 3 Jan 2009 11:49 | Modified: | 15 May 2009 12:50 |
| Reporter: | Philip Stoev | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Falcon storage engine | Severity: | S1 (Critical) |
| Version: | 6.0-falcon-team | OS: | Any |
| Assigned to: | Kevin Lewis | CPU Architecture: | Any |
| Tags: | F_RECORD TREE | ||
[3 Jan 2009 11:51]
Philip Stoev
The default --falcon-page-size is also affected.
[5 Jan 2009 16:40]
Kevin Lewis
Ann, Please ask Jim to take a look. The member variable StorageTable::record is null during a call to StorageTable::updateRow(). How could this happen?
[7 Jan 2009 5:57]
Kevin Lewis
I reproduced this crash running combinations.yy and found that Table::checkAncestor() was being called immediately after Table::fetch(), which can return a null. The test for null needs to be put before the call to Table::checkAncestor().
[7 Jan 2009 6:14]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/62565 2956 Kevin Lewis 2009-01-07 Bug#41835 - Table::getSyncPrior() was called with a null record pointer because Table::checkAncestor() was called immediately after Table::fetch(), which can return a null.
[13 Feb 2009 7:24]
Bugs System
Pushed into 6.0.10-alpha (revid:alik@sun.com-20090211182317-uagkyj01fk30p1f8) (version source revid:olav@sun.com-20090113103017-41jbad7qlvlwpwxh) (merge vers: 6.0.10-alpha) (pib:6)
[15 May 2009 12:50]
MC Brown
A note has been added to the 6.0.10 changelog: Running concurrent non-transactional queries on a Falcon table could cause a crash.

Description: When executing concurrent non-transactional update, insert, replace queries, Falcon crashed as follows: #2 <signal handler called> #3 Table::getSyncPrior (record=0x0, this=0x7fd771f819d0) at Table.cpp:3825 #4 Table::checkAncestor (this=0x7fd771f819d0, current=0x0, oldRecord=0x2b44360) at Table.cpp:3473 #5 0x0000000000866b93 in Table::update (this=0x7fd771f819d0, transaction=0x7fd771fa26b8, orgRecord=0x2b44360, stream=0x7fd771fe1ed0) at Table.cpp:3097 #6 0x000000000084fe07 in StorageDatabase::updateRow (this=<value optimized out>, storageConnection=<value optimized out>, table=0x7fd771f819d0, oldRecord=0x2b44360, stream=0x7fd771fe1ed0) at StorageDatabase.cpp:688 #7 0x000000000085544e in StorageTable::updateRow (this=0x7fd771fdc930, recordNumber=<value optimized out>) at StorageTable.cpp:132 #8 0x000000000084b351 in StorageInterface::update_row (this=0x7fd76c002318, oldData=<value optimized out>, newData=0x7fd76c014868 "ВЪШ") at ha_falcon.cpp:1196 #9 0x00000000007555e0 in handler::ha_update_row (this=0x7fd76c002318, old_data=0x7fd76c014b28 "ВЪЪ", new_data=0x7fd76c014868 "ВЪШ") at handler.cc:5462 #10 0x00000000006f0373 in mysql_update (thd=0x2b1a540, table_list=<value optimized out>, fields=@0x2b1c5c8, values=@0x2b1c9d0, conds=0x0, order_num=<value optimized out>, order=0x2b25b30, limit=2, handle_duplicates=DUP_ERROR, ignore=false) at sql_update.cc:649 #11 0x0000000000667244 in mysql_execute_command (thd=0x2b1a540) at sql_parse.cc:3005 #12 0x000000000066adb8 in mysql_parse (thd=0x2b1a540, inBuf=0x2b24ff8 "UPDATE `table100_falcon_int_autoinc` SET `char_64_key_latin1` = 'come' ORDER BY `int_unsigned_key` LIMIT 3", length=107, found_semicolon=0x7fd75f250070) at sql_parse.cc:5735 #13 0x000000000066ba7e in dispatch_command (command=COM_QUERY, thd=0x2b1a540, packet=0x2b1cfc1 "UPDATE `table100_falcon_int_autoinc` SET `char_64_key_latin1` = 'come' ORDER BY `int_unsigned_key` LIMIT 3", packet_length=<value optimized out>) at sql_parse.cc:1007 #14 0x000000000065f938 in handle_one_connection (arg=<value optimized out>) at sql_connect.cc:1145 #15 0x000000315b0073da in start_thread () from /lib64/libpthread.so.0 #16 0x000000315a4e627d in clone () from /lib64/libc.so.6 (gdb) list 3820 } 3821 } 3822 3823 SyncObject* Table::getSyncPrior(Record* record) 3824 { 3825 int recNumber = (record->recordNumber == -1) ? 0 : record->recordNumber; 3826 int lockNumber = recNumber % SYNC_VERSIONS_SIZE; 3827 return syncPriorVersions + lockNumber; 3828 } 3829 (gdb) print record $2 = (class Record *) 0x0 How to repeat: $ perl runall.pl \ --mysqld=--falcon-page-size=8K \ --mem \ --rows=100 \ --threads=16 \ --mask=38 \ --queries=1000000 \ --duration=300 \ --basedir=/build/bzr/6.0-falcon-team \ --engine=Falcon \ --grammar=conf/combinations.yy \ --gendata=conf/combinations.zz \ --reporter=Backtrace \ --mysqld=--loose-falcon-lock-wait-timeout=1 \ --mysqld=--log-output=none Note that only the update, insert, replace portions of the grammar are used. You may hit other crashes with that test case, so just run it a dozen times if necessary.