summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@mariadb.com>2021-01-11 08:34:04 +0200
committerJan Lindström <jan.lindstrom@mariadb.com>2021-01-11 08:34:04 +0200
commitd1aea01dd3438225a2adcca19d79f7a9ff22c8f8 (patch)
treea6fec29df398b8abf2e51dd18c117d84ca04d783
parent3b548d3bbf888e7c9e9853cf826e528b5195d8bd (diff)
downloadmariadb-git-bb-10.2-MDEV-23536.tar.gz
MDEV-23536 : Race condition between KILL and transaction commitbb-10.2-MDEV-23536
Fix test regression. We need to pass information do we hold THD::LOCK_thd_data mutex to close_thread_table, close_thread_tables and Locked_tables_list::unlock_locked_tables because unlock_locked_tables would otherwise take it.
-rw-r--r--sql/sql_base.cc16
-rw-r--r--sql/sql_base.h4
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h2
-rw-r--r--storage/innobase/handler/ha_innodb.cc2
5 files changed, 14 insertions, 12 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b8d18abb50c..d6cf79f35a6 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -717,7 +717,7 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
leave prelocked mode if needed.
*/
-void close_thread_tables(THD *thd)
+void close_thread_tables(THD *thd, bool have_mutex)
{
TABLE *table;
DBUG_ENTER("close_thread_tables");
@@ -856,7 +856,7 @@ void close_thread_tables(THD *thd)
other thread tries to abort the MERGE lock in between.
*/
while (thd->open_tables)
- (void) close_thread_table(thd, &thd->open_tables);
+ (void) close_thread_table(thd, &thd->open_tables, have_mutex);
DBUG_VOID_RETURN;
}
@@ -864,7 +864,7 @@ void close_thread_tables(THD *thd)
/* move one table to free list */
-void close_thread_table(THD *thd, TABLE **table_ptr)
+void close_thread_table(THD *thd, TABLE **table_ptr, bool have_mutex)
{
TABLE *table= *table_ptr;
DBUG_ENTER("close_thread_table");
@@ -889,9 +889,11 @@ void close_thread_table(THD *thd, TABLE **table_ptr)
table->file->update_global_index_stats();
}
- mysql_mutex_lock(&thd->LOCK_thd_data);
+ if (!have_mutex)
+ mysql_mutex_lock(&thd->LOCK_thd_data);
*table_ptr=table->next;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
+ if (!have_mutex)
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
if (! table->needs_reopen())
{
@@ -2193,7 +2195,7 @@ Locked_tables_list::init_locked_tables(THD *thd)
*/
void
-Locked_tables_list::unlock_locked_tables(THD *thd)
+Locked_tables_list::unlock_locked_tables(THD *thd, bool have_mutex)
{
DBUG_ASSERT(!thd->in_sub_stmt &&
!(thd->state_flags & Open_tables_state::BACKUPS_AVAIL));
@@ -2221,7 +2223,7 @@ Locked_tables_list::unlock_locked_tables(THD *thd)
TRANSACT_TRACKER(clear_trx_state(thd, TX_LOCKED_TABLES));
DBUG_ASSERT(thd->transaction.stmt.is_empty());
- close_thread_tables(thd);
+ close_thread_tables(thd, have_mutex);
/*
We rely on the caller to implicitly commit the
diff --git a/sql/sql_base.h b/sql/sql_base.h
index b67341bcbda..55b0aa645cf 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -147,7 +147,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
TABLE_LIST *TABLE_LIST::*link,
const char *db_name,
const char *table_name);
-void close_thread_tables(THD *thd);
+void close_thread_tables(THD *thd, bool have_mutex=false);
void switch_to_nullable_trigger_fields(List<Item> &items, TABLE *);
void switch_defaults_to_nullable_trigger_fields(TABLE *table);
bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
@@ -269,7 +269,7 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
uint dt_phases);
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
int decide_logging_format(THD *thd, TABLE_LIST *tables);
-void close_thread_table(THD *thd, TABLE **table_ptr);
+void close_thread_table(THD *thd, TABLE **table_ptr, bool have_mutex=false);
TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
uint check_flag);
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 2321991d99f..1d024860c5b 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1374,7 +1374,7 @@ void THD::cleanup(bool have_mutex)
#endif
mysql_ha_cleanup(this);
- locked_tables_list.unlock_locked_tables(this);
+ locked_tables_list.unlock_locked_tables(this, have_mutex);
delete_dynamic(&user_var_events);
close_temporary_tables();
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a97f64c13b3..714821f4c46 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1845,7 +1845,7 @@ public:
init_sql_alloc(&m_locked_tables_root, MEM_ROOT_BLOCK_SIZE, 0,
MYF(MY_THREAD_SPECIFIC));
}
- void unlock_locked_tables(THD *thd);
+ void unlock_locked_tables(THD *thd, bool have_mutex=false);
void unlock_locked_table(THD *thd, MDL_ticket *mdl_ticket);
~Locked_tables_list()
{
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c79b3423b63..d3d8c8bb4e9 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -128,7 +128,7 @@ void destroy_thd(MYSQL_THD thd);
void reset_thd(MYSQL_THD thd);
TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,
const char *tb, size_t tblen);
-void close_thread_tables(THD* thd);
+void close_thread_tables(THD* thd, bool have_mutex=false);
/** Check if user has used xtradb extended system variable that
is not currently supported by innodb or marked as deprecated. */