summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gorrod <alexg@wiredtiger.com>2015-04-23 05:43:35 +0000
committerMichael Cahill <michael.cahill@mongodb.com>2015-04-25 12:50:52 +1000
commit80226f628ca53f9076db8061abaa55dbda1b0674 (patch)
treeac3f69b8f3817ecca0224eec539686ddf548f854
parent785fab985bcbd01fb351bfca5f5362f7eea69516 (diff)
downloadmongo-80226f628ca53f9076db8061abaa55dbda1b0674.tar.gz
Fix a deadlock related to handle locking.
If one thread does a __wt_session_release_btree of a handle at the same time as another thread does a __wt_session_get_btree both wanting exclusive access to the file. It was possible for one thread to get the dhandle list lock and wait on the handle lock, which another thread held the handle lock waiting for the handle list lock. Temporarily fix by doing a try-lock on the __wt_session_get_btree path, long term the solution is to get rid of the __conn_dhandle_open_lock method, and split get and lock into two passes. Refs BF-716
-rw-r--r--src/conn/conn_dhandle.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/src/conn/conn_dhandle.c b/src/conn/conn_dhandle.c
index 385280116a6..0eb3389de34 100644
--- a/src/conn/conn_dhandle.c
+++ b/src/conn/conn_dhandle.c
@@ -70,9 +70,9 @@ __conn_dhandle_open_lock(
return (EBUSY);
/*
- * If the handle is open, get a read lock and recheck.
+ * If the handle is open, try to get a read lock and recheck.
*
- * Wait for a read lock if we want exclusive access and failed
+ * Try to get a read lock if we want exclusive access and failed
* to get it: the sweep server may be closing this handle, and
* we need to wait for it to complete. If we want exclusive
* access and find the handle open once we get the read lock,
@@ -80,7 +80,15 @@ __conn_dhandle_open_lock(
*/
if (F_ISSET(dhandle, WT_DHANDLE_OPEN) &&
(!want_exclusive || lock_busy)) {
- WT_RET(__wt_readlock(session, dhandle->rwlock));
+ ret = __wt_try_readlock(session, dhandle->rwlock);
+ if (ret == EBUSY) {
+ if (want_exclusive &&
+ F_ISSET(dhandle, WT_DHANDLE_OPEN))
+ return (ret);
+ __wt_yield();
+ continue;
+ }
+ WT_RET(ret);
is_open = F_ISSET(dhandle, WT_DHANDLE_OPEN) ? 1 : 0;
if (is_open && !want_exclusive)
return (0);