Bug #11832 Server crash with InnoDB + Cursors
Submitted: 9 Jul 2005 11:23 Modified: 10 Aug 2005 15:15
Reporter: Georg Richter Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S1 (Critical)
Version:5.0.7 OS:Linux (Linux)
Assigned to: Konstantin Osipov CPU Architecture:Any

[9 Jul 2005 11:23] Georg Richter
Description:
When a 2nd connection alters a table which is open with a cursor client application hangs. After terminating the client application with Ctrl+C the server crashes.
This bug only occurs when autocommit is on.

trace:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1442933680 (LWP 27765)]
0x0835490e in fseg_free_step (header=0x424b804a "", mtr=0x56012300)
    at fsp0fsp.c:3202
3202            ut_a(descr);
Current language:  auto; currently c
(gdb) bt
#0  0x0835490e in fseg_free_step (header=0x424b804a "", mtr=0x56012300)
    at fsp0fsp.c:3202
#1  0x083211a3 in btr_free_but_not_root (space=11, root_page_no=3)
    at btr0btr.c:776
#2  0x082eea37 in dict_drop_index_tree (rec=0x423cc3d2 "", mtr=0x56012990)
    at dict0crea.c:704
#3  0x0831575a in row_upd_clust_step (node=0x4227f298, thr=0x422803b8)
    at row0upd.c:1679
#4  0x08315ad5 in row_upd (node=0x4227f298, thr=0x422803b8) at row0upd.c:1819
#5  0x08315cc6 in row_upd_step (thr=0x422803b8) at row0upd.c:1948
#6  0x082fc2f3 in que_thr_step (thr=0x422803b8) at que0que.c:1171
#7  0x082fc4bd in que_run_threads (thr=0x422803b8) at que0que.c:1248
#8  0x08309e08 in row_drop_table_for_mysql (name=0x56012f50 "test/t1",
    trx=0x42275468, drop_db=0) at row0mysql.c:3286
#9  0x08273b8b in ha_innobase::delete_table (this=0x8c70a68,
    name=0x560150d0 "./test/t1") at ha_innodb.cc:4853
#10 0x08262d58 in ha_delete_table (thd=0x8c42f20, table_type=DB_TYPE_INNODB,
    path=0x560150d0 "./test/t1", alias=0x8c708f0 "t1", generate_warning=true)
    at handler.cc:1275
#11 0x0827afd2 in mysql_rm_table_part2 (thd=0x8c42f20, tables=0x8c70918,
    if_exists=true, drop_temporary=false, drop_view=false,
    dont_log_query=false) at sql_table.cc:276
#12 0x0827a9a4 in mysql_rm_table (thd=0x8c42f20, tables=0x8c70918,

How to repeat:
/* 
   bug_0708_1.c
   server crash with open cursor and alter table
*/

#include <stdio.h>
#include <mysql.h>

MYSQL_STMT *open_cursor(MYSQL *mysql, char *query)
{
  ulong ctype = CURSOR_TYPE_READ_ONLY;
  MYSQL_STMT *stmt = mysql_stmt_init(mysql);

  mysql_stmt_prepare(stmt, query, strlen(query));
  mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &ctype);

  return stmt;
}

int main() {
  MYSQL *mysql[2];   
  MYSQL_STMT *stmt;
   
  mysql[0] = mysql_init(NULL);
  mysql[1] = mysql_init(NULL);
  mysql_real_connect(mysql[0], "localhost", "root", "", "test", 0, NULL, 0);
  mysql_real_connect(mysql[1], "localhost", "root", "", "test", 0, NULL, 0);

  mysql_query(mysql[0], "SET @@autocommit=1");
  mysql_query(mysql[1], "SET @@autocommit=1");

  mysql_query(mysql[1], "DROP TABLE IF EXISTS t1");
  mysql_query(mysql[1], "CREATE TABLE t1 (a int, index(a)) engine=InnoDB");
  mysql_query(mysql[1], "INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7)");

  stmt = open_cursor(mysql[0], "SELECT a FROM t1 WHERE a in (3,4)");
  mysql_stmt_execute(stmt);

  mysql_stmt_fetch(stmt);

  printf("Press Ctrl + C to crash MySQL server\n");
  mysql_query(mysql[1], "ALTER TABLE t1 DROP INDEX a");

  mysql_stmt_fetch(stmt);

  mysql_stmt_close(stmt);
  mysql_close(mysql[0]);
  mysql_close(mysql[1]);
}
[10 Jul 2005 4:48] Aleksey Kishkin
tested and realized that this example works even with 5.0.7.

0x8099c42 handle_segfault + 430
0x8342fb8 pthread_sighandler + 184
0x82307ba trx_free + 626
0x82318d9 trx_free_for_mysql + 689
0x812f473 innobase_close_connection__FP3THD + 35
0x8125d71 ha_close_connection__FP3THD + 49
0x808f676 _._3THD + 142
0x8099850 end_thread__FP3THDb + 64
0x80a81c8 handle_one_connection + 1056
0x834076c pthread_start_thread + 220
0x836a17a thread_start + 4
[11 Jul 2005 11:09] Heikki Tuuri
Hi!

I do not understand how Georg got InnoDB to crash inside fsp0fsp.c. The crash by Alexei Kishkin looks more natural.

MySQL should not allow a table to be DROPped or ALTERed when there is an open cursor to it. Or, the cursor should be 'released' in such a situation.

Regards,

Heikki
[11 Jul 2005 12:04] Georg Richter
Heikki,

my backtrace was not correct. The first time it crashes in trxotrx.c (trx_free). When starting the test again table t1 is corrupted and a simple select on this table crashes the server.
[29 Jul 2005 10:49] Andrey Hristov
The fix for 11813 didn't fix that one. Tried with today's snapshot which has no problems with 11813. The stack trace is very similar to 12243 and 12263.
[6 Aug 2005 9:12] Konstantin Osipov
Georg, do you have a non-interactive test case for this bug?
I'd love to add it to the test suite.
[6 Aug 2005 17:07] Andrey Hristov
Konstantin, I don't see much interactivity :) IMO this could be added to the test suite only the printf() should be removed.
[8 Aug 2005 9:14] Konstantin Osipov
Andrey,
if you try this test case with the patch I sent you, you'll see that now ALTER TABLE hangs in the second connection.
One needs to press ctrl-c (abort the connection) to abort that alter table.
[8 Aug 2005 10:07] Andrey Hristov
I see
[10 Aug 2005 14:36] 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/internals/28111
[10 Aug 2005 15:02] Konstantin Osipov
Approved by Heikki Tuuri via email.
[10 Aug 2005 15:03] Konstantin Osipov
Fixed in 5.0 tree, currently tagged 5.0.12
[10 Aug 2005 15:15] Jon Stephens
Thank you for your bug report. This issue has been committed to our
source repository of that product and will be incorporated into the
next release.

If necessary, you can access the source repository and build the latest
available version, including the bugfix, yourself. More information 
about accessing the source trees is available at
    http://www.mysql.com/doc/en/Installing_source_tree.html

Additional info:

Documented in 5.0.12 change history.