From bcb36ee21e2515d17dcf03b760487e64eb780f2b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 20 Apr 2018 10:10:33 +0200 Subject: MDEV-15456 Server crashes upon adding or dropping a partition in ALTER under LOCK TABLE after ER_SAME_NAME_PARTITION ALTER TABLE ... ADD PARTITION modifies the open TABLE structure, and sets table->need_reopen=1 to reset these modifications in case of an error. But under LOCK TABLES the table isn't get reopened, despite need_reopen. Fixed by reopening need_reopen tables under LOCK TABLE. --- sql/sql_base.cc | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'sql/sql_base.cc') diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 964f82e7331..7d27e87180c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -568,7 +568,7 @@ err_with_reopen: old locks. This should always succeed (unless some external process has removed the tables) */ - thd->locked_tables_list.reopen_tables(thd); + thd->locked_tables_list.reopen_tables(thd, false); /* Since downgrade_lock() won't do anything with shared metadata lock it is much simpler to go through all open tables rather @@ -952,7 +952,10 @@ void close_thread_tables(THD *thd) we will exit this function a few lines below. */ if (! thd->lex->requires_prelocking()) + { + thd->locked_tables_list.reopen_tables(thd, true); DBUG_VOID_RETURN; + } /* We are in the top-level statement of a prelocked statement, @@ -2973,7 +2976,7 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) */ bool -Locked_tables_list::reopen_tables(THD *thd) +Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) { Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); size_t reopen_count= 0; @@ -2984,8 +2987,20 @@ Locked_tables_list::reopen_tables(THD *thd) for (TABLE_LIST *table_list= m_locked_tables; table_list; table_list= table_list->next_global) { - if (table_list->table) /* The table was not closed */ - continue; + if (need_reopen) + { + if (!table_list->table || !table_list->table->needs_reopen()) + continue; + /* no need to remove the table from the TDC here, thus (TABLE*)1 */ + close_all_tables_for_name(thd, table_list->table->s, + HA_EXTRA_NOT_USED, (TABLE*)1); + DBUG_ASSERT(table_list->table == NULL); + } + else + { + if (table_list->table) /* The table was not closed */ + continue; + } /* Links into thd->open_tables upon success */ if (open_table(thd, table_list, thd->mem_root, &ot_ctx)) -- cgit v1.2.1 From f2433b8dd3c10b1e26a6f0b98dfbaa45b22fe0af Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 21 Apr 2018 13:13:19 +0200 Subject: MDEV-10824 - Crash in CREATE OR REPLACE TABLE t1 AS SELECT spfunc() followup for a3c980b381ea same change in Locked_tables_list::unlink_from_list(), otherwise thd->locked_tables_list will keep pointers to a free'd TABLE if prelocked under lock tables. This fixes a crash in main.create_or_replace on debug Win builds after bcb36ee21e25 --- sql/sql_base.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql/sql_base.cc') diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7d27e87180c..f7de4e4f3c2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2872,7 +2872,8 @@ void Locked_tables_list::unlink_from_list(THD *thd, If mode is not LTM_LOCK_TABLES, we needn't do anything. Moreover, outside this mode pos_in_locked_tables value is not trustworthy. */ - if (thd->locked_tables_mode != LTM_LOCK_TABLES) + if (thd->locked_tables_mode != LTM_LOCK_TABLES && + thd->locked_tables_mode != LTM_PRELOCKED_UNDER_LOCK_TABLES) return; /* -- cgit v1.2.1