#At file:///home/satya/WORK/mysql-5.1-bugteam-41330/ based on revid:timothy.smith@stripped
2853 Satya B 2009-04-02 [merge]
merge 5.0-bugteam to 5.1-bugteam
added:
mysql-test/r/myisam_crash_before_flush_keys.result
mysql-test/t/myisam_crash_before_flush_keys-master.opt
mysql-test/t/myisam_crash_before_flush_keys.test
modified:
storage/myisam/mi_close.c
=== added file 'mysql-test/r/myisam_crash_before_flush_keys.result'
--- a/mysql-test/r/myisam_crash_before_flush_keys.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/myisam_crash_before_flush_keys.result 2009-04-02 09:47:34 +0000
@@ -0,0 +1,42 @@
+#
+# BUG#41330 - Myisam table open count set to zero before index blocks are written.
+#
+# Don't test this under valgrind, memory leaks will occur
+# Binary must be compiled with debug for crash to occur
+SET GLOBAL delay_key_write=ALL;
+CREATE TABLE t1(a INT,
+b INT,
+PRIMARY KEY(a , b),
+KEY(b)) ENGINE=MyISAM DELAY_KEY_WRITE = 1;
+INSERT INTO t1 VALUES (1,2),(2,3),(3,4),(4,5),(5,6);
+SHOW GLOBAL STATUS LIKE 'Key_blocks%';
+Variable_name Value
+Key_blocks_not_flushed 2
+Key_blocks_unused 902
+Key_blocks_used 4
+# Setup the mysqld to crash at certain point
+SET SESSION debug="d,crash_before_flush_keys";
+# Write file to make mysql-test-run.pl expect crash
+# Run the crashing query
+FLUSH TABLE t1;
+ERROR HY000: Lost connection to MySQL server during query
+# Run MYISAMCHK tool to check the table t1 and repair
+# Write file to make mysql-test-run.pl start the server
+# Turn on reconnect
+# Call script that will poll the server waiting for it to be back online again
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL DEFAULT '0',
+ `b` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`a`,`b`),
+ KEY `b` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1
+SELECT * FROM t1 FORCE INDEX (PRIMARY);
+a b
+1 2
+2 3
+3 4
+4 5
+5 6
+DROP TABLE t1;
=== added file 'mysql-test/t/myisam_crash_before_flush_keys-master.opt'
--- a/mysql-test/t/myisam_crash_before_flush_keys-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/myisam_crash_before_flush_keys-master.opt 2009-04-02 09:47:34 +0000
@@ -0,0 +1 @@
+--skip-stack-trace --skip-core-file
=== added file 'mysql-test/t/myisam_crash_before_flush_keys.test'
--- a/mysql-test/t/myisam_crash_before_flush_keys.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/myisam_crash_before_flush_keys.test 2009-04-02 09:47:34 +0000
@@ -0,0 +1,47 @@
+--echo #
+--echo # BUG#41330 - Myisam table open count set to zero before index blocks are written.
+--echo #
+--source include/not_embedded.inc
+--echo # Don't test this under valgrind, memory leaks will occur
+--source include/not_valgrind.inc
+
+--echo # Binary must be compiled with debug for crash to occur
+--source include/have_debug.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+SET GLOBAL delay_key_write=ALL;
+CREATE TABLE t1(a INT,
+ b INT,
+ PRIMARY KEY(a , b),
+ KEY(b)) ENGINE=MyISAM DELAY_KEY_WRITE = 1;
+INSERT INTO t1 VALUES (1,2),(2,3),(3,4),(4,5),(5,6);
+
+SHOW GLOBAL STATUS LIKE 'Key_blocks%';
+
+--echo # Setup the mysqld to crash at certain point
+SET SESSION debug="d,crash_before_flush_keys";
+
+--echo # Write file to make mysql-test-run.pl expect crash
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+
+--echo # Run the crashing query
+--error 2013
+FLUSH TABLE t1;
+
+--echo # Run MYISAMCHK tool to check the table t1 and repair
+--exec $MYISAMCHK -crs $MYSQLD_DATADIR/test/t1
+
+--echo # Write file to make mysql-test-run.pl start the server
+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+
+--echo # Turn on reconnect
+--enable_reconnect
+
+--echo # Call script that will poll the server waiting for it to be back online again
+--source include/wait_until_connected_again.inc
+
+SHOW CREATE TABLE t1;
+
+SELECT * FROM t1 FORCE INDEX (PRIMARY);
+
+DROP TABLE t1;
=== modified file 'storage/myisam/mi_close.c'
--- a/storage/myisam/mi_close.c 2007-05-10 09:59:39 +0000
+++ b/storage/myisam/mi_close.c 2009-04-02 09:47:34 +0000
@@ -35,8 +35,8 @@ int mi_close(register MI_INFO *info)
if (info->lock_type == F_EXTRA_LCK)
info->lock_type=F_UNLCK; /* HA_EXTRA_NO_USER_CHANGE */
- if (share->reopen == 1 && share->kfile >= 0)
- _mi_decrement_open_count(info);
+ DBUG_EXECUTE_IF("crash_before_flush_keys",
+ if(info->s->global_changed && (info->s->state.open_count !=0)) abort(););
if (info->lock_type != F_UNLCK)
{
@@ -78,6 +78,8 @@ int mi_close(register MI_INFO *info)
*/
if (share->mode != O_RDONLY && mi_is_crashed(info))
mi_state_info_write(share->kfile, &share->state, 1);
+ /* Decrement open count must be last I/O on this file. */
+ _mi_decrement_open_count(info);
if (my_close(share->kfile,MYF(0)))
error = my_errno;
}