diff options
author | Yuhong Zhang <yuhong.zhang@mongodb.com> | 2022-03-28 13:20:31 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-06-11 19:18:23 +0000 |
commit | 0b631bd20851f04838616a4f00a29ff8a0320767 (patch) | |
tree | 9639c3aa0602f6193561be12b76838e26632ca84 | |
parent | 2f1e8dc34c7ddfa1c9dccab011759a12532c8219 (diff) | |
download | mongo-0b631bd20851f04838616a4f00a29ff8a0320767.tar.gz |
SERVER-55173 Skip releasing cursors during shutdown to avoid segmentation fault
(cherry picked from commit bc940d6b0adc9254b62e9daf9c92d2c92f8b083d)
(cherry picked from commit 7a074786f4048e3ac304dfbab12a5fafd5f14f00)
3 files changed, 31 insertions, 1 deletions
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp index c80ac13d70b..ff545f445b4 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp @@ -131,6 +131,11 @@ WT_CURSOR* WiredTigerSession::getReadOnceCursor(const std::string& uri, bool all } void WiredTigerSession::releaseCursor(uint64_t id, WT_CURSOR* cursor) { + // Avoids the cursor already being destroyed during the shutdown. + if (_cache->isShuttingDown()) { + return; + } + invariant(_session); invariant(cursor); _cursorsOut--; @@ -227,6 +232,10 @@ void WiredTigerSessionCache::shuttingDown() { closeAll(); } +bool WiredTigerSessionCache::isShuttingDown() { + return _shuttingDown.load() & kShuttingDownMask; +} + void WiredTigerSessionCache::waitUntilDurable(bool forceCheckpoint, bool stableCheckpoint) { // For inMemory storage engines, the data is "as durable as it's going to get". // That is, a restart is equivalent to a complete node failure. @@ -416,7 +425,8 @@ UniqueWiredTigerSession WiredTigerSessionCache::getSession() { void WiredTigerSessionCache::releaseSession(WiredTigerSession* session) { invariant(session); - invariant(session->cursorsOut() == 0); + // 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); }); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h index 5c44b4cbd08..89d95ad7ed0 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.h @@ -259,6 +259,11 @@ public: */ void shuttingDown(); + /** + * True when in the process of shutting down. + */ + bool isShuttingDown(); + bool isEphemeral(); /** * Waits until all commits that happened before this call are durable, either by flushing diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache_test.cpp index 8cfd3d1ddc5..59ad59bb3f8 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache_test.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache_test.cpp @@ -113,4 +113,19 @@ TEST(WiredTigerSessionCacheTest, CheckSessionCacheCleanup) { ASSERT_EQUALS(sessionCache->getIdleSessionsCount(), 0U); } +TEST(WiredTigerSessionCacheTest, ReleaseCursorDuringShutdown) { + WiredTigerSessionCacheHarnessHelper harnessHelper(""); + WiredTigerSessionCache* sessionCache = harnessHelper.getSessionCache(); + UniqueWiredTigerSession session = sessionCache->getSession(); + // Simulates the cursor already being deleted during shutdown. + WT_CURSOR* cursor = nullptr; + + sessionCache->shuttingDown(); + ASSERT(sessionCache->isShuttingDown()); + + auto tableIdWeDontCareAbout = WiredTigerSession::genTableId(); + // Skips actually trying to release the cursor to avoid the segmentation fault. + session->releaseCursor(tableIdWeDontCareAbout, cursor); +} + } // namespace mongo |