diff options
author | Keith Bostic <keith@wiredtiger.com> | 2015-08-16 17:05:52 -0400 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2015-08-25 15:47:15 +1000 |
commit | 36d6e156d62356caa15ef3df8d43212f1c32f4d1 (patch) | |
tree | 6552389a5fa5bc174e75cfaee96990e87f69ff16 /src/btree | |
parent | 0a9e47902e106ac7e38d733720dcc78356515a08 (diff) | |
download | mongo-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.c | 15 |
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); |