diff options
author | Yuhong Zhang <yuhong.zhang@mongodb.com> | 2022-05-23 13:41:25 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-05-31 18:12:21 +0000 |
commit | b1b34b9541fda4d4c5517aa8dae5c0159bde3cce (patch) | |
tree | ec1fee473f07d4ac878500d7b8ea7ef62eec2ace /src | |
parent | 66ab552d94f76d328ab09fb37dffd655884fb262 (diff) | |
download | mongo-b1b34b9541fda4d4c5517aa8dae5c0159bde3cce.tar.gz |
SERVER-66556 Block shutdown when releasing cursors to avoid race conditions
(cherry picked from commit 66e938045f87c72f379eb0def449b62bde97721c)
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h | 17 |
2 files changed, 25 insertions, 8 deletions
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp index d7997dee2c5..3ed1d4e985b 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp @@ -137,6 +137,10 @@ WT_CURSOR* WiredTigerSession::getNewCursor(const std::string& uri, const char* c } void WiredTigerSession::releaseCursor(uint64_t id, WT_CURSOR* cursor, const std::string& config) { + // When releasing the cursor, we would want to check if the session cache is already in shutdown + // and prevent the race condition that the shutdown starts after the check. + WiredTigerSessionCache::BlockShutdown blockShutdown(_cache); + // Avoids the cursor already being destroyed during the shutdown. if (_cache->isShuttingDown()) { return; @@ -230,7 +234,7 @@ void WiredTigerSessionCache::shuttingDown() { if (_shuttingDown.fetchAndBitOr(kShuttingDownMask) & kShuttingDownMask) return; - // Spin as long as there are threads in releaseSession + // Spin as long as there are threads blocking shutdown. while (_shuttingDown.load() != kShuttingDownMask) { sleepmillis(1); } @@ -265,12 +269,11 @@ void WiredTigerSessionCache::waitUntilDurable(OperationContext* opCtx, return; } - const int shuttingDown = _shuttingDown.fetchAndAdd(1); - ON_BLOCK_EXIT([this] { _shuttingDown.fetchAndSubtract(1); }); + BlockShutdown blockShutdown(this); uassert(ErrorCodes::ShutdownInProgress, "Cannot wait for durability because a shutdown is in progress", - !(shuttingDown & kShuttingDownMask)); + !isShuttingDown()); // Stable checkpoints are only meaningful in a replica set. Replication sets the "stable // timestamp". If the stable timestamp is unset, WiredTiger takes a full checkpoint, which is @@ -486,10 +489,9 @@ void WiredTigerSessionCache::releaseSession(WiredTigerSession* session) { // We might have skipped releasing some cursors during the shutdown. invariant(session->cursorsOut() == 0 || isShuttingDown()); - const int shuttingDown = _shuttingDown.fetchAndAdd(1); - ON_BLOCK_EXIT([this] { _shuttingDown.fetchAndSubtract(1); }); + BlockShutdown blockShutdown(this); - if (shuttingDown & kShuttingDownMask) { + if (isShuttingDown()) { // There is a race condition with clean shutdown, where the storage engine is ripped from // underneath OperationContexts, which are not "active" (i.e., do not have any locks), but // are just about to delete the recovery unit. See SERVER-16031 for more information. Since diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h index 960ad11e75c..18da44e3246 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h @@ -245,6 +245,21 @@ public: */ enum class UseJournalListener { kUpdate, kSkip }; + // RAII type to block and unblock the WiredTigerSessionCache to shut down. + class BlockShutdown { + public: + BlockShutdown(WiredTigerSessionCache* cache) : _cache(cache) { + _cache->_shuttingDown.fetchAndAdd(1); + } + + ~BlockShutdown() { + _cache->_shuttingDown.fetchAndSubtract(1); + } + + private: + WiredTigerSessionCache* _cache; + }; + /** * Indicates that WiredTiger should be configured to cache cursors. */ @@ -374,7 +389,7 @@ private: WiredTigerSnapshotManager _snapshotManager; // Used as follows: - // The low 31 bits are a count of active calls to releaseSession. + // The low 31 bits are a count of active calls that need to block shutdown. // The high bit is a flag that is set if and only if we're shutting down. AtomicWord<unsigned> _shuttingDown; static const uint32_t kShuttingDownMask = 1 << 31; |