mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 10:14:19 +01:00
MDEV-22529 thd_query_safe() isn’t, causing InnoDB to hang
The function thd_query_safe() is used in the implementation of the following INFORMATION_SCHEMA views: information_schema.innodb_trx information_schema.innodb_locks information_schema.innodb_lock_waits information_schema.rocksdb_trx The implementation of the InnoDB views is in trx_i_s_common_fill_table(). This function invokes trx_i_s_possibly_fetch_data_into_cache(), which will acquire lock_sys->mutex and trx_sys->mutex in order to protect the set of active transactions and explicit locks. While holding those mutexes, it will traverse the collection of InnoDB transactions. For each transaction, thd_query_safe() will be invoked. When called via trx_i_s_common_fill_table(), thd_query_safe() is acquiring THD::LOCK_thd_data while holding the InnoDB locks. This will cause a deadlock with THD::awake() (such as executing KILL QUERY), because THD::awake() could invoke lock_trx_handle_wait(), which attempts to acquire lock_sys->mutex while already holding THD::lock_thd_data. thd_query_safe(): Invoke mysql_mutex_trylock() instead of mysql_mutex_lock(). Return the empty string if the mutex cannot be acquired without waiting.
This commit is contained in:
parent
b57c6cb394
commit
a2560b0077
1 changed files with 14 additions and 4 deletions
|
@ -4530,6 +4530,7 @@ extern "C" LEX_STRING * thd_query_string (MYSQL_THD thd)
|
|||
@param buflen Length of the buffer
|
||||
|
||||
@return Length of the query
|
||||
@retval 0 if LOCK_thd_data cannot be acquired without waiting
|
||||
|
||||
@note This function is thread safe as the query string is
|
||||
accessed under mutex protection and the string is copied
|
||||
|
@ -4538,10 +4539,19 @@ extern "C" LEX_STRING * thd_query_string (MYSQL_THD thd)
|
|||
|
||||
extern "C" size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen)
|
||||
{
|
||||
mysql_mutex_lock(&thd->LOCK_thd_data);
|
||||
size_t len= MY_MIN(buflen - 1, thd->query_length());
|
||||
memcpy(buf, thd->query(), len);
|
||||
mysql_mutex_unlock(&thd->LOCK_thd_data);
|
||||
size_t len= 0;
|
||||
/* InnoDB invokes this function while holding internal mutexes.
|
||||
THD::awake() will hold LOCK_thd_data while invoking an InnoDB
|
||||
function that would acquire the internal mutex. Because this
|
||||
function is a non-essential part of information_schema view output,
|
||||
we will break the deadlock by avoiding a mutex wait here
|
||||
and returning the empty string if a wait would be needed. */
|
||||
if (!mysql_mutex_trylock(&thd->LOCK_thd_data))
|
||||
{
|
||||
len= MY_MIN(buflen - 1, thd->query_length());
|
||||
memcpy(buf, thd->query(), len);
|
||||
mysql_mutex_unlock(&thd->LOCK_thd_data);
|
||||
}
|
||||
buf[len]= '\0';
|
||||
return len;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue