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:
None 
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
Triage: Triaged: D1 (Critical)

[3 Jan 2009 11:49] Philip Stoev
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.
[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.