Bug#45781 infinite hang/crash in "opening tables" after handler tries to open merge
table The MERGE table storage engine does not support the HA_CAN_SQL_HANDLE feature and any attempt to open the merge table will fail with ER_ILLEGAL_HA. After an error occurred the tables that was opened must be closed again or they will be left in an inconsistent state. However, the assumption made in the code for closing and register handler tables was that only one table will be opened, and this is not true for MERGE tables which will cause multiple tables to open. The next time a SELECT operation was issued on the merge table it caused the system to freeze. This patch fixes this issue by making sure that all tables which are opened also are closed in the event of an error.
This commit is contained in:
parent
5b178e9a2a
commit
c9df2a13ac
@ -2141,4 +2141,24 @@ SELECT * FROM m1;
|
||||
c1
|
||||
DROP TABLE m1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug45781 infinite hang/crash in "opening tables" after handler tries to
|
||||
# open merge table
|
||||
#
|
||||
DROP TABLE IF EXISTS m1,t1;
|
||||
CREATE TABLE t1(a int)engine=myisam;
|
||||
CREATE TABLE t2(a int)engine=myisam;
|
||||
CREATE TABLE t3(a int)engine=myisam;
|
||||
CREATE TABLE t4(a int)engine=myisam;
|
||||
CREATE TABLE t5(a int)engine=myisam;
|
||||
CREATE TABLE t6(a int)engine=myisam;
|
||||
CREATE TABLE t7(a int)engine=myisam;
|
||||
CREATE TABLE m1(a int)engine=merge union=(t1,t2,t3,t4,t5,t6,t7);
|
||||
SELECT 1 FROM m1;
|
||||
1
|
||||
HANDLER m1 OPEN;
|
||||
ERROR HY000: Table storage engine for 'm1' doesn't have this option
|
||||
DROP TABLE m1,t1,t2,t3,t4,t5,t6,t7;
|
||||
SELECT 1 FROM m1;
|
||||
ERROR 42S02: Table 'test.m1' doesn't exist
|
||||
End of 5.1 tests
|
||||
|
@ -1555,4 +1555,28 @@ SELECT * FROM m1;
|
||||
DROP TABLE m1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Bug45781 infinite hang/crash in "opening tables" after handler tries to
|
||||
--echo # open merge table
|
||||
--echo #
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS m1,t1;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1(a int)engine=myisam;
|
||||
CREATE TABLE t2(a int)engine=myisam;
|
||||
CREATE TABLE t3(a int)engine=myisam;
|
||||
CREATE TABLE t4(a int)engine=myisam;
|
||||
CREATE TABLE t5(a int)engine=myisam;
|
||||
CREATE TABLE t6(a int)engine=myisam;
|
||||
CREATE TABLE t7(a int)engine=myisam;
|
||||
CREATE TABLE m1(a int)engine=merge union=(t1,t2,t3,t4,t5,t6,t7);
|
||||
SELECT 1 FROM m1;
|
||||
--error ER_ILLEGAL_HA
|
||||
HANDLER m1 OPEN;
|
||||
DROP TABLE m1,t1,t2,t3,t4,t5,t6,t7;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SELECT 1 FROM m1; # Should not hang!
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
@ -252,14 +252,37 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
|
||||
|
||||
/* for now HANDLER can be used only for real TABLES */
|
||||
tables->required_type= FRMTYPE_TABLE;
|
||||
/*
|
||||
We use open_tables() here, rather than, say,
|
||||
open_ltable() or open_table() because we would like to be able
|
||||
to open a temporary table.
|
||||
*/
|
||||
error= open_tables(thd, &tables, &counter, 0);
|
||||
/* restore the state and merge the opened table into handler_tables list */
|
||||
if (thd->open_tables)
|
||||
{
|
||||
thd->open_tables->next= thd->handler_tables;
|
||||
thd->handler_tables= thd->open_tables;
|
||||
if (thd->open_tables->next)
|
||||
{
|
||||
/*
|
||||
We opened something that is more than a single table.
|
||||
This happens with MERGE engine. Don't try to link
|
||||
this mess into thd->handler_tables list, close it
|
||||
and report an error. We must do it right away
|
||||
because mysql_ha_close_table(), called down the road,
|
||||
can close a single table only.
|
||||
*/
|
||||
close_thread_tables(thd);
|
||||
my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
|
||||
error= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Merge the opened table into handler_tables list. */
|
||||
thd->open_tables->next= thd->handler_tables;
|
||||
thd->handler_tables= thd->open_tables;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore the state. */
|
||||
thd->open_tables= backup_open_tables;
|
||||
|
||||
if (error)
|
||||
|
Loading…
x
Reference in New Issue
Block a user