Bug #31286 Falcon crashes when falcon_record_memory_max is exceeded
Submitted: 28 Sep 2007 18:39 Modified: 5 May 2008 16:57
Reporter: Giuseppe Maxia Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Falcon storage engine Severity:S1 (Critical)
Version:6.0.3 OS:Linux (2.6.19-1.2911.6.5.fc6 #1 SMP)
Assigned to: Kevin Lewis CPU Architecture:Any
Tags: crash, falcon, record buffer

[28 Sep 2007 18:39] Giuseppe Maxia
Description:
When a table exceeds falcon_record_memory_max, the server crashes.

There are two cases:

1) if falcon_record_memory_max is below 113 MB, then the server does not crash, but the query fails (as expected) with 
error 1296: Got error 305 'record memory is exhausted' from Falcon

2) if falcon_record_memory_max is over 113 MB, the server crashes when the memory limit is reached.
2013: Lost connection to MySQL server during query
Here the server crashes and dumps core

How to repeat:
--disable_warnings
drop table if exists t1;
--enable_warnings

set global falcon_record_memory_max = 1024 * 1024 * 113;

create table t1 (id int ) engine = falcon ;

insert into t1 values (1);

let $counter = 21;

while ($counter)
{
    select @delta := (select count(*) from t1 );
    insert into t1 select id + @delta  from t1;
    dec $counter ;
}

drop table t1;
[28 Sep 2007 20:50] Kevin Lewis
I caught this crash in a stack overflow.  I think it is a different behavior than before.  

This happens when the maximum record memory size is exceeded.  During a call to Database::forceRecordScavenge() from Record::allocRecordData(), the call stack gets down into Table::inventoryRecords() and then eventually into RecordScavenge::inventoryRecord().  In this function, a call is made to record->getRecordData(), which causes RecordVersion::thaw() to be called.  In order to thaw the record, it makes another call to Record::allocRecordData(), which calls Database::forceRecordScavenge(), and we have a recursive loop that finally ends when the stack overflows.

I am investigating how to fix this.
[28 Sep 2007 20:59] Hakan Küçükyılmaz
Backtrace is:
Program received signal SIGSEGV, Segmentation fault.
0x00002b8f13c1a894 in vfprintf () from /lib/libc.so.6
(gdb) bt
#0  0x00002b8f13c1a894 in vfprintf () from /lib/libc.so.6
#1  0x00002b8f13c403fa in vsnprintf () from /lib/libc.so.6
#2  0x0000000000866362 in SQLError (this=0x102a390, 
    code=OUT_OF_RECORD_MEMORY_ERROR, txt=0xaff970 "record memory is exhausted")
    at SQLError.cpp:62
#3  0x00000000008382ef in MemMgr::allocRaw (this=<value optimized out>, 
    length=2097152) at MemMgr.cpp:817
#4  0x00000000008385a0 in MemMgr::alloc (this=0xf795e0, length=72)
    at MemMgr.cpp:470
#5  0x000000000083866e in MemMgr::allocateDebug (this=0x40843620, size=8, 
    fileName=0xb03138 "Record.cpp", line=943) at MemMgr.cpp:544
#6  0x0000000000839479 in MemMgrPoolAllocateDebug (pool=0x40843620, 
    s=11532656, file=0x40843b90 "\030", line=0) at MemMgr.cpp:116
#7  0x000000000084716a in Record::allocRecordData (this=0x7f30950, length=8)
    at MemoryManager.h:72
#8  0x000000000084744d in Record::setEncodedRecord (this=0x7f30950, 
    stream=0x40843df0, interlocked=true) at Record.cpp:686
#9  0x0000000000848d6e in RecordVersion::thaw (this=0x7f30950)
    at RecordVersion.cpp:298
#10 0x0000000000848973 in RecordScavenge::inventoryRecord (this=0x408447f0, 
    record=0x7f30950) at Record.h:116
#11 0x0000000000846995 in RecordLeaf::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x408447f0)
---Type <return> to continue, or q <return> to quit---
    at RecordLeaf.cpp:247
#12 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x408447f0)
    at RecordGroup.cpp:192
#13 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x408447f0)
    at RecordGroup.cpp:192
#14 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x408447f0)
    at RecordGroup.cpp:192
#15 0x00000000007f836e in Table::inventoryRecords (this=0x2aaaaacf8808, 
    recordScavenge=0x408447f0) at Table.cpp:1612
#16 0x0000000000816f20 in Database::retireRecords (this=0x2aaaaaaaeb98, 
    forced=true) at Database.cpp:1648
#17 0x0000000000817156 in Database::forceRecordScavenge (this=0x40843620)
    at Database.cpp:2264
#18 0x00000000008471c6 in Record::allocRecordData (this=0x7f30950, length=8)
    at Record.cpp:950
#19 0x000000000084744d in Record::setEncodedRecord (this=0x7f30950, 
    stream=0x408449f0, interlocked=true) at Record.cpp:686
#20 0x0000000000848d6e in RecordVersion::thaw (this=0x7f30950)
    at RecordVersion.cpp:298
#21 0x0000000000848973 in RecordScavenge::inventoryRecord (this=0x408453f0, 
---Type <return> to continue, or q <return> to quit---
    record=0x7f30950) at Record.h:116
#22 0x0000000000846995 in RecordLeaf::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x408453f0)
    at RecordLeaf.cpp:247
#23 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x408453f0)
    at RecordGroup.cpp:192
#24 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x408453f0)
    at RecordGroup.cpp:192
#25 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x408453f0)
    at RecordGroup.cpp:192
#26 0x00000000007f836e in Table::inventoryRecords (this=0x2aaaaacf8808, 
    recordScavenge=0x408453f0) at Table.cpp:1612
#27 0x0000000000816f20 in Database::retireRecords (this=0x2aaaaaaaeb98, 
    forced=true) at Database.cpp:1648
#28 0x0000000000817156 in Database::forceRecordScavenge (this=0x40843620)
    at Database.cpp:2264
#29 0x00000000008471c6 in Record::allocRecordData (this=0x7f30950, length=8)
    at Record.cpp:950
#30 0x000000000084744d in Record::setEncodedRecord (this=0x7f30950, 
    stream=0x408455f0, interlocked=true) at Record.cpp:686
---Type <return> to continue, or q <return> to quit---
#31 0x0000000000848d6e in RecordVersion::thaw (this=0x7f30950
    at RecordVersion.cpp:298
#32 0x0000000000848973 in RecordScavenge::inventoryRecord (this=0x40845ff0, 
    record=0x7f30950) at Record.h:116
#33 0x0000000000846995 in RecordLeaf::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x40845ff0)
    at RecordLeaf.cpp:247
#34 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x40845ff0)
    at RecordGroup.cpp:192
#35 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x40845ff0)
    at RecordGroup.cpp:192
#36 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x40845ff0)
    at RecordGroup.cpp:192
#37 0x00000000007f836e in Table::inventoryRecords (this=0x2aaaaacf8808, 
    recordScavenge=0x40845ff0) at Table.cpp:1612
#38 0x0000000000816f20 in Database::retireRecords (this=0x2aaaaaaaeb98, 
    forced=true) at Database.cpp:1648
#39 0x0000000000817156 in Database::forceRecordScavenge (this=0x40843620)
    at Database.cpp:2264
#40 0x00000000008471c6 in Record::allocRecordData (this=0x7f30950, length=8)
---Type <return> to continue, or q <return> to quit---
    at Record.cpp:950
#41 0x000000000084744d in Record::setEncodedRecord (this=0x7f30950, 
    stream=0x408461f0, interlocked=true) at Record.cpp:686
#42 0x0000000000848d6e in RecordVersion::thaw (this=0x7f30950)
    at RecordVersion.cpp:298
#43 0x0000000000848973 in RecordScavenge::inventoryRecord (this=0x40846bf0, 
    record=0x7f30950) at Record.h:116
#44 0x0000000000846995 in RecordLeaf::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x40846bf0)
    at RecordLeaf.cpp:247
#45 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x40846bf0)
    at RecordGroup.cpp:192
#46 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x40846bf0)
    at RecordGroup.cpp:192
#47 0x0000000000890b3e in RecordGroup::inventoryRecords (
    this=<value optimized out>, recordScavenge=0x40846bf0)
    at RecordGroup.cpp:192
#48 0x00000000007f836e in Table::inventoryRecords (this=0x2aaaaacf8808, 
    recordScavenge=0x40846bf0) at Table.cpp:1612
#49 0x0000000000816f20 in Database::retireRecords (this=0x2aaaaaaaeb98, 
    forced=true) at Database.cpp:1648
---Type <return> to continue, or q <return> to quit---
[16 Oct 2007 17:19] Kevin Lewis
Fixed in mysql-6.0-falcon-team
[16 Oct 2007 20:23] Hakan Küçükyılmaz
I have to fix the Intel/Mac build issue before Giuseppe can verify the fix for this bug.

Best regards,

Hakan
[30 Nov 2007 13:24] Hakan Küçükyılmaz
Giuseppe,

the Mac/Intel build of Falcon works again. Can you test this again using mysql-6.0-falcon-team tree?

Thanks,

Hakan
[30 Nov 2007 20:43] Bugs System
Pushed into 6.0.4-alpha
[5 May 2008 16:57] Paul DuBois
Noted in 6.0.4 changelog.

Falcon could crash when the maximum record size was exceeded.