Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug #1405076: Deadlock in RELEASE_LOCK()
The RELEASE_LOCK() implementation introduced by the multiple user level locks patch can result in a deadlock under the following conditions: - connection #1 calls RELEASE_LOCK() for a previously acquired lock. In which case MDL_lock::remove_ticket() is called, which write-locks MDL_lock::m_rwlock corresponding to the user-level MDL object. With that lock held, MDL_map_partition::remove() is called which locks MDL_map_partition::m_mutex protecting the hash of MDL locks belonging to an MDL partition. - connection #2 calls RELEASE_LOCK() simultaneously for the same lock being released by connection #1. Since connection #2 did not own the lock, it calls MDL_map_partition::get_lock_owner() to check if 0 or NULL should be returned (i.e. if the lock exists). That function also locks both MDL_map_partition::m_mutex and MDL_lock::m_rwlock(), but in the reverse order as compared to connection #1. With the right timing for the above events we get each thread waiting for a lock acquired by the other thread, i.e. a deadlock. Fixed by avoiding to lock MDL_lock::m_rwlock with MDL_map_partition::m_mutex locked. There is already infrastructure to release the latter and acquire the former and guarantee that a reference to an MDL_lock object is valid at the same time. It is implemented in MDL_map_partition::move_from_hash_to_lock_mutex(), so the fix utilizes it to remove the deadlock condition. (cherry picked from commit 4c1eeb4) Conflicts: sql/mdl.cc
- Loading branch information