diff options
author | Andrew Shuvalov <andrew.shuvalov@mongodb.com> | 2021-05-21 16:07:01 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-05-21 16:46:27 +0000 |
commit | f25468750488f8445794805873df5de456d9c557 (patch) | |
tree | 53e70931f760fc2b64b1b4b833b9ee6c0b2fcddb /src/mongo/client/replica_set_monitor_integration_test.cpp | |
parent | 2cb0ba6b43491c2aa564b6d93a5612132d69549e (diff) | |
download | mongo-f25468750488f8445794805873df5de456d9c557.tar.gz |
SERVER-56523: potential deadlock - avoid locking the ReplicaSetMonitorManager mutex when garbage collecting RSM
Diffstat (limited to 'src/mongo/client/replica_set_monitor_integration_test.cpp')
-rw-r--r-- | src/mongo/client/replica_set_monitor_integration_test.cpp | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/mongo/client/replica_set_monitor_integration_test.cpp b/src/mongo/client/replica_set_monitor_integration_test.cpp index e8b51797431..3f2af0e8ce4 100644 --- a/src/mongo/client/replica_set_monitor_integration_test.cpp +++ b/src/mongo/client/replica_set_monitor_integration_test.cpp @@ -194,6 +194,38 @@ TEST_F(ReplicaSetMonitorFixture, ReplicaSetMonitorCleanup) { ASSERT_TRUE(cleanupInvoked); } +// Tests that RSM Manager registerForGarbageCollection() could be invoked while holding a +// lvl 2 mutex. Tests that GC is invoked before creating a new monitor. +TEST_F(ReplicaSetMonitorFixture, LockOrderingAndGC) { + ReplicaSetMonitor::cleanup(); + ASSERT_EQ(0, ReplicaSetMonitorManager::get()->getAllSetNames().size()); + auto monitor = ReplicaSetMonitor::createIfNeeded(replSetUri); + ASSERT_EQ(1, ReplicaSetMonitorManager::get()->getAllSetNames().size()); + const auto previousGCCount = + ReplicaSetMonitorManager::get()->getGarbageCollectedMonitorsCount(); + + { + auto lvl2mutex = MONGO_MAKE_LATCH(HierarchicalAcquisitionLevel(2), "lvl2mutex"); + stdx::unique_lock lk(lvl2mutex); + // This invokes delayed GC that locks only lvl 1 mutex. + monitor.reset(); + // Tests that GC was not run yet. + ASSERT_EQ(previousGCCount, + ReplicaSetMonitorManager::get()->getGarbageCollectedMonitorsCount()); + } + + // Tests that GC was not invoked yet and the empty pointer is still in the cache. + ASSERT_EQ(1, ReplicaSetMonitorManager::get()->getNumMonitors()); + // getAllSetNames() checks that each pointer is valid, thus it returns 0. + ASSERT_EQ(0, ReplicaSetMonitorManager::get()->getAllSetNames().size()); + + ReplicaSetMonitor::createIfNeeded(replSetUri); + // Tests that GC was run. + ASSERT_EQ(previousGCCount + 1, + ReplicaSetMonitorManager::get()->getGarbageCollectedMonitorsCount()); + ASSERT_EQ(0, ReplicaSetMonitorManager::get()->getAllSetNames().size()); +} + } // namespace } // namespace executor } // namespace mongo |