summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorYuhong Zhang <yuhong.zhang@mongodb.com>2022-05-23 13:41:25 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-05-31 18:12:21 +0000
commitb1b34b9541fda4d4c5517aa8dae5c0159bde3cce (patch)
treeec1fee473f07d4ac878500d7b8ea7ef62eec2ace /src/mongo
parent66ab552d94f76d328ab09fb37dffd655884fb262 (diff)
downloadmongo-b1b34b9541fda4d4c5517aa8dae5c0159bde3cce.tar.gz
SERVER-66556 Block shutdown when releasing cursors to avoid race conditions
(cherry picked from commit 66e938045f87c72f379eb0def449b62bde97721c)
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp16
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h17
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;