Commit 322a5a39 authored by Davi Arnaut's avatar Davi Arnaut

Bug#41110: crash with handler command when used concurrently with alter table

Bug#41112: crash in mysql_ha_close_table/get_lock_data with alter table

The problem is that the server wasn't handling robustly failures
to re-open a table during a HANDLER .. READ statement. If the
table needed to be re-opened due to it's storage engine being
altered to one that doesn't support HANDLER, a reference (dangling
pointer) to a closed table could be left in place and accessed in
later attempts to fetch from the table using the handler. Also,
if the server failed to set a error message if the re-open
failed. These problems could lead to server crashes or hangs.

The solution is to remove any references to a closed table and
to set a error if reopening a table during a HANDLER .. READ
statement fails.

There is no test case in this change set as the test depends on
a testing feature only available on 5.1 and later.
parent 1fbfd317
......@@ -151,6 +151,9 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables)
}
VOID(pthread_mutex_unlock(&LOCK_open));
}
/* Mark table as closed, ready for re-open if necessary. */
tables->table= NULL;
}
/*
......@@ -168,8 +171,7 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables)
'reopen' is set when a handler table is to be re-opened. In this case,
'tables' is the pointer to the hashed TABLE_LIST object which has been
saved on the original open.
'reopen' is also used to suppress the sending of an 'ok' message or
error messages.
'reopen' is also used to suppress the sending of an 'ok' message.
RETURN
FALSE OK
......@@ -205,8 +207,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
strlen(tables->alias) + 1))
{
DBUG_PRINT("info",("duplicate '%s'", tables->alias));
if (! reopen)
my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
goto err;
}
}
......@@ -251,8 +252,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
/* There can be only one table in '*tables'. */
if (! (tables->table->file->table_flags() & HA_CAN_SQL_HANDLER))
{
if (! reopen)
my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
goto err;
}
......@@ -464,8 +464,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (need_reopen)
{
mysql_ha_close_table(thd, tables);
hash_tables->table= NULL;
mysql_ha_close_table(thd, hash_tables);
/*
The lock might have been aborted, we need to manually reset
thd->some_tables_deleted because handler's tables are closed
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment