mirror of
https://github.com/MariaDB/server.git
synced 2025-07-05 12:42:17 +03:00
MDEV-23536 Race condition between KILL and transaction commit
Server part: kill_handlerton() was accessing thd->ha_data[] for some other thd, while it could be concurrently modified by its owner thd. protect thd->ha_data[] modifications with a mutex. require this mutex when accessing thd->ha_data[] from kill_handlerton. InnoDB part: on close_connection, detach trx from thd before freeing the trx
This commit is contained in:
@ -838,6 +838,7 @@ static my_bool kill_handlerton(THD *thd, plugin_ref plugin,
|
||||
{
|
||||
handlerton *hton= plugin_hton(plugin);
|
||||
|
||||
mysql_mutex_assert_owner(&thd->LOCK_thd_data);
|
||||
if (hton->state == SHOW_OPTION_YES && hton->kill_query &&
|
||||
thd_get_ha_data(thd, hton))
|
||||
hton->kill_query(hton, thd, *(enum thd_kill_levels *) level);
|
||||
|
@ -444,6 +444,7 @@ void thd_set_ha_data(THD *thd, const struct handlerton *hton,
|
||||
const void *ha_data)
|
||||
{
|
||||
plugin_ref *lock= &thd->ha_data[hton->slot].lock;
|
||||
DBUG_ASSERT(thd == current_thd);
|
||||
if (ha_data && !*lock)
|
||||
*lock= ha_lock_engine(NULL, (handlerton*) hton);
|
||||
else if (!ha_data && *lock)
|
||||
@ -451,7 +452,9 @@ void thd_set_ha_data(THD *thd, const struct handlerton *hton,
|
||||
plugin_unlock(NULL, *lock);
|
||||
*lock= NULL;
|
||||
}
|
||||
mysql_mutex_lock(&thd->LOCK_thd_data);
|
||||
*thd_ha_data(thd, hton)= (void*) ha_data;
|
||||
mysql_mutex_unlock(&thd->LOCK_thd_data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5117,6 +5117,7 @@ innobase_close_connection(
|
||||
|
||||
if (trx) {
|
||||
|
||||
thd_set_ha_data(thd, hton, NULL);
|
||||
if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
|
||||
|
||||
sql_print_error("Transaction not registered for MariaDB 2PC, "
|
||||
|
Reference in New Issue
Block a user