diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-10-21 20:41:10 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-10-21 20:41:10 +0300 |
commit | 4f59f9078fd9af1e958f4a30788084598053bf50 (patch) | |
tree | a2ec7a8be96098370ad61e890410a200717e0191 | |
parent | 193f9df9bc4c353c0c3bd259da8afab545c14130 (diff) | |
download | mariadb-git-4f59f9078fd9af1e958f4a30788084598053bf50.tar.gz |
Fix hang due to lock_sys_t::cancel()
TODO: file a bug for this
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 6abbc58f9be..234d215d1df 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -5690,10 +5690,25 @@ dberr_t lock_sys_t::cancel(trx_t *trx, lock_t *lock) { resolve_table_lock: dict_table_t *table= lock->un_member.tab_lock.table; - table->lock_mutex_lock(); + if (!table->lock_mutex_trylock()) + { + /* The correct latching order is: + lock_sys.latch, table->lock_mutex_lock(), lock_sys.wait_mutex. + Thus, we must release lock_sys.wait_mutex for a blocking wait. */ + mysql_mutex_unlock(&lock_sys.wait_mutex); + table->lock_mutex_lock(); + mysql_mutex_lock(&lock_sys.wait_mutex); + lock= trx->lock.wait_lock; + if (!lock) + goto retreat; + else if (check_victim && trx->lock.was_chosen_as_deadlock_victim) + { + err= DB_DEADLOCK; + goto retreat; + } + } if (lock->is_waiting()) lock_cancel_waiting_and_release(lock); - table->lock_mutex_unlock(); /* Even if lock->is_waiting() did not hold above, we must return DB_LOCK_WAIT, or otherwise optimistic parallel replication could occasionally hang. Potentially affected tests: @@ -5701,6 +5716,8 @@ resolve_table_lock: rpl.rpl_parallel_optimistic_nobinlog rpl.rpl_parallel_optimistic_xa_lsu_off */ err= DB_LOCK_WAIT; +retreat: + table->lock_mutex_unlock(); } lock_sys.rd_unlock(); } |