summaryrefslogtreecommitdiff
path: root/src/btree
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2015-08-16 17:05:52 -0400
committerMichael Cahill <michael.cahill@mongodb.com>2015-08-25 15:47:15 +1000
commit36d6e156d62356caa15ef3df8d43212f1c32f4d1 (patch)
tree6552389a5fa5bc174e75cfaee96990e87f69ff16 /src/btree
parent0a9e47902e106ac7e38d733720dcc78356515a08 (diff)
downloadmongo-36d6e156d62356caa15ef3df8d43212f1c32f4d1.tar.gz
WT-2045: Avoid a potential deadlock in the eviction server.
There are two places in the page-read code where a reading thread calls __wt_cache_eviction_check without first checking the WT_READ_NO_EVICT flag, and that can lead to deadlock. The case I have is a configuration with no eviction-worker threads, lots of eviction pressure, and so the application threads are busy doing eviction. The eviction server thread splits a page, is getting a hazard pointer on the parent, and for some reason can't get it immediately. The eviction server thread then gets pressed into doing more eviction, there are no pages on the queue because the application threads have emptied it, and things stall forever while the eviction server looks for pages on the empty eviction queue. (cherry picked from commit 7c8ce54f261faaf643ce5d063f27bb78db0c2cd8)
Diffstat (limited to 'src/btree')
-rw-r--r--src/btree/bt_page.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/src/btree/bt_page.c b/src/btree/bt_page.c
index a38c96c77a4..3ae3ee23e58 100644
--- a/src/btree/bt_page.c
+++ b/src/btree/bt_page.c
@@ -81,10 +81,12 @@ __wt_page_in_func(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t flags
return (WT_NOTFOUND);
/*
- * The page isn't in memory, attempt to read it.
- * Make sure there is space in the cache.
+ * The page isn't in memory, read it. If this thread is
+ * allowed to do eviction work, check for space in the
+ * cache.
*/
- WT_RET(__wt_cache_full_check(session));
+ if (!LF_ISSET(WT_READ_NO_EVICT))
+ WT_RET(__wt_cache_full_check(session));
WT_RET(__wt_cache_read(session, ref));
oldgen = LF_ISSET(WT_READ_WONT_NEED) ||
F_ISSET(session, WT_SESSION_NO_CACHE);
@@ -185,6 +187,13 @@ __wt_page_in_func(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t flags
if (++wait_cnt < 1000)
__wt_yield();
else {
+ /*
+ * If stalling and this thread is allowed to do eviction
+ * work, check if the cache needs help.
+ */
+ if (!LF_ISSET(WT_READ_NO_EVICT))
+ WT_RET(__wt_cache_full_check(session));
+
sleep_cnt = WT_MIN(wait_cnt, 10000);
wait_cnt *= 2;
WT_STAT_FAST_CONN_INCRV(session, page_sleep, sleep_cnt);