summaryrefslogtreecommitdiff
path: root/sql/mdl.cc
diff options
context:
space:
mode:
authorJon Olav Hauglid <jon.hauglid@sun.com>2009-12-16 12:32:11 +0100
committerJon Olav Hauglid <jon.hauglid@sun.com>2009-12-16 12:32:11 +0100
commit6d4e09d68e1ea104e84e1f9bafffe43b00a7aec9 (patch)
tree99bc3c53514e9ebc3d7f1cac2b8c8bb443b1d3d7 /sql/mdl.cc
parent980e8b413e89175d8fc7f867415712589bead9ff (diff)
downloadmariadb-git-6d4e09d68e1ea104e84e1f9bafffe43b00a7aec9.tar.gz
Bug #48541 Deadlock between LOCK_open and LOCK_mdl
The reason for the deadlock was an improper exit from MDL_context::wait_for_locks() which caused mysys_var->current_mutex to remain LOCK_mdl even though LOCK_mdl was no longer held by that connection. This could for example lead to a deadlock in the following way: 1) INSERT DELAYED tries to open a table but fails, and trying to recover it calls wait_for_locks(). 2) Due to a pending exclusive request, wait_for_locks() fails and exits without resetting mysys_var->current_mutex for the delayed insert handler thread. So it continues to point to LOCK_mdl. 3) The handler thread manages to open a table. 4) A different connection takes LOCK_open and tries to take LOCK_mdl. 5) FLUSH TABLES from a third connection notices that the handler thread has a table open, and tries to kill it. This involves locking mysys_var->current_mutex while having LOCK_open locked. Since current_mutex mistakenly points to LOCK_mdl, we have a deadlock. This patch makes sure MDL_EXIT_COND() is called before exiting wait_for_locks(). This clears mysys->current_mutex which resolves the issue. An assert is added to recover_from_failed_open_table_attempt() after wait_for_locks() is called, to check that current_mutex is indeed reset. With this assert in place, existing tests in (e.g.) mdl_sync.test will fail without this patch.
Diffstat (limited to 'sql/mdl.cc')
-rw-r--r--sql/mdl.cc3
1 files changed, 2 insertions, 1 deletions
diff --git a/sql/mdl.cc b/sql/mdl.cc
index a883b21423e..6187d4515a3 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -1254,7 +1254,8 @@ MDL_context::wait_for_locks(MDL_request_list *mdl_requests)
}
if (!mdl_request)
{
- pthread_mutex_unlock(&LOCK_mdl);
+ /* As a side-effect MDL_EXIT_COND() unlocks LOCK_mdl. */
+ MDL_EXIT_COND(m_thd, mysys_var, old_msg);
break;
}
pthread_cond_wait(&COND_mdl, &LOCK_mdl);