Bug #37344 Crash in IndexWalker::rebalanceDelete

Submitted: 11 Jun 2008 13:59 Modified: 30 Sep 2008 20:08
Reporter: Philip Stoev Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Falcon storage engine Severity:S1 (Critical)
Version:6.0-falcon OS:Any
Assigned to: Ann Harrison CPU Architecture:Any

[11 Jun 2008 13:59] Philip Stoev
Description:
When executing a DML workload, Falcon crashed as follows:

#0  0x00110416 in __kernel_vsyscall ()
#1  0x00581c78 in pthread_kill () from /lib/libpthread.so.0
#2  0x0843eda3 in write_core (sig=11) at stacktrace.c:302
#3  0x0829b228 in handle_segfault (sig=11) at mysqld.cc:2626
#4  <signal handler called>
#5  0x08524157 in IndexWalker::rebalanceDelete (this=0xb73999b0) at IndexWalker.cpp:272
#6  0x085245f3 in IndexWalker::rebalanceUpward (this=0xb73999b0, delta=1) at IndexWalker.cpp:481
#7  0x08524692 in IndexWalker::remove (this=0xb63d1400) at IndexWalker.cpp:430
#8  0x0852489a in IndexWalker::getNext (this=0xb7378550, lockForUpdate=false) at IndexWalker.cpp:89
#9  0x084aef38 in StorageDatabase::nextIndexed (this=0xb7201130, storageTable=0xb75dead0, indexWalker=0xb7378550, lockForUpdate=false)
    at StorageDatabase.cpp:481
#10 0x084b589c in StorageTable::nextIndexed (this=0xb75dead0, recordNumber=1268, lockForUpdate=false) at StorageTable.cpp:180
#11 0x084a8485 in StorageInterface::index_next (this=0xa5c54c8, buf=0xa5c5690 "Э\230\004") at ha_falcon.cpp:1585
#12 0x083c6059 in handler::read_range_next (this=0xa5c54c8) at handler.cc:4947
#13 0x083c418c in handler::multi_range_read_next (this=0xa5c54c8, range_info=0xa9c9bbf0) at handler.cc:4241
#14 0x083a3c7a in QUICK_RANGE_SELECT::get_next (this=0xa481830) at opt_range.cc:8508
#15 0x083be315 in rr_quick (info=0xa5849a4) at records.cc:298
#16 0x08315db8 in sub_select (join=0xa432dc8, join_tab=0xa584960, end_of_records=false) at sql_select.cc:13351
#17 0x08322d70 in do_select (join=0xa432dc8, fields=0xa434124, table=0x0, procedure=0x0) at sql_select.cc:13092
#18 0x08335655 in JOIN::exec (this=0xa432dc8) at sql_select.cc:2740
#19 0x083308f2 in mysql_select (thd=0xa4a9470, rref_pointer_array=0xa9d00bf4, tables=0xa9d01170, wild_num=0, fields=@0xa9d00b84, conds=0xa9d01480, og_num=1,
    order=0x0, group=0xa9d01610, having=0x0, proc_param=0x0, select_options=2416724480, result=0xa5d92b0, unit=0xa9d00c88, select_lex=0xa9d00af0)
    at sql_select.cc:2929
#20 0x0843e6f8 in mysql_derived_filling (thd=0xa4a9470, lex=0xa4aa540, orig_table_list=0xa9d01910) at sql_derived.cc:264
#21 0x0843e4a3 in mysql_handle_derived (lex=0xa4aa540, processor=0x843e528 <mysql_derived_filling(THD*, st_lex*, TABLE_LIST*)>) at sql_derived.cc:56
#22 0x082f890f in open_and_lock_tables_derived (thd=0xa4a9470, tables=0xa9d01910, derived=true) at sql_base.cc:4929
#23 0x082b7921 in open_and_lock_tables (thd=0xa4a9470, tables=0xa9d01910) at mysql_priv.h:1606
#24 0x082aa403 in execute_sqlcom_select (thd=0xa4a9470, all_tables=0xa9d01910) at sql_parse.cc:4789
#25 0x082ac0c9 in mysql_execute_command (thd=0xa4a9470) at sql_parse.cc:2018
#26 0x082b4ec6 in mysql_parse (thd=0xa4a9470,
    inBuf=0xa9d00500 "SELECT AVG( int_key ) FROM ( SELECT AVG( int_nokey ) FROM o AS X WHERE X . int_key < 44 GROUP BY int_key LIMIT 20 ) AS X WHERE X . int_key < 69 GROUP BY int_key", length=160, found_semicolon=0xa9c9d260) at sql_parse.cc:5782
#27 0x082b590f in dispatch_command (command=COM_QUERY, thd=0xa4a9470,
    packet=0xa4aae69 "SELECT AVG( int_key ) FROM ( SELECT AVG( int_nokey ) FROM o AS X WHERE X . int_key < 44 GROUP BY int_key LIMIT 20 ) AS X WHERE X . int_key < 69 GROUP BY int_key", packet_length=160) at sql_parse.cc:1059
#28 0x082b6b75 in do_command (thd=0xa4a9470) at sql_parse.cc:732
#29 0x082a4385 in handle_one_connection (arg=0xa4a9470) at sql_connect.cc:1134
#30 0x0057d32f in start_thread () from /lib/libpthread.so.0
#31 0x0049a27e in clone () from /lib/libc.so.6

The code is:

267
268     bool IndexWalker::rebalanceDelete()
269     {
270             if (balance > 1)
271                     {
272                     if (higher->balance < 0)
273                             {
274                             higher->rotateRight();
275                             rotateLeft();

The crash is because:

(gdb) print higher
$1 = (IndexWalker *) 0x0

How to repeat:
A simplifed test case will hopefully follow shortly.
[12 Jun 2008 10:29] Philip Stoev
Unsimplifed test case for bug 37344

Attachment: bug37344.test (application/octet-stream, text), 128.51 KiB.

[12 Jun 2008 10:36] Philip Stoev
Please find attached a non-simplifed test case for this bug. Let me know if a simpler test case is required to fix this bug and I will work on it.

Basically this crash happens on a statement of the form (either standalone or in a subquery):

SELECT AVG( int_nokey ) FROM E AS X WHERE X . int_nokey < 69 GROUP BY int_key LIMIT 1;

It is not sufficient to simply insert the data (the top of the test case) and then issue the SELECT (the last statement of the test case) -- at least some of the UPDATE operations (the middle of the test case) are also required.
[20 Jun 2008 21:15] Ann Harrison
In IndexWalker, the class member "balance" is not initialized.
[29 Jun 2008 11:44] Philip Stoev
I added  balance = 0; to IndexWalker::IndexWalker, however the crash still happened on a longer run. The existing test case no longer fails, so I will try to provide a new one.
[29 Jun 2008 13:09] Philip Stoev
The problem is that "higher" it not initialized:

(gdb) print higher
$2 = (IndexWalker *) 0x0
(gdb) print higher->balance
Cannot access memory at address 0x0
[29 Jun 2008 13:19] Philip Stoev
Grammar file for bug 37344

Attachment: bug37344.yy (text/plain), 1.54 KiB.

[29 Jun 2008 13:24] Philip Stoev
To reproduce the issue, please check out the mysql-test-extra-6.0 tree and then:

$ cd mysql-test-extra-6.0/mysql-test/gentest
$ ./runall.pl --basedir=/path/to/mysql-6.0-falcon --engine=Falcon --grammar=/location/of/bug37344.yy

This script will proceed to start a server and run randomly generated queries based on the grammar file. The crash will happen within 10 min after takeoff. Please ignore any errors reported by the test script itself -- it is not always able to generate semantically valid queries.

The grammar file may contain queries that are not related to the bug in question. Please let me know if a simplifed test case, or a test case in a different format is required.

It appears that the index must arrive to a certain state in order to crash, and it is very likely that any insert/update/delete mixture will arrive to a broken index eventually.
[29 Jun 2008 22:39] Ann Harrison
If higher were not initialized, it would be 0XCCCCCC - zero is 
a legitimate value for higher.  The code in question is rebalancing
an AVL tree - at the lowest levels, both higher and lower are zero.
That's not to say that there isn't a bug, just that having higher
be zero is not necessarily the cause.
[10 Jul 2008 18:49] Philip Stoev
New grammar for bug 37344

Attachment: bug37344.yy (application/octet-stream, text), 988 bytes.

[25 Jul 2008 18:11] Ann Harrison
Change pushed to the team tree seems to solve the problem
[27 Jul 2008 2:10] Kevin Lewis
Patch Approved, Code looks good.
[29 Jul 2008 11:37] Kevin Lewis
Pushed to mysql-6.0-falcon-team
[22 Aug 2008 21:15] Kevin Lewis
This is fixed in version 6.0.6
[30 Sep 2008 20:08] Jon Stephens
Documented as follows in the 6.0.6 changelog:

        A large number of updates on a Falcon table followed by a query of the
        form SELECT AVG(int_non_key_column) FROM table AS x WHERE
        int_non_key_column < constant GROUP BY int_key_column LIMIT limit
        could crash the server.

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.067 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.