summaryrefslogtreecommitdiff
path: root/src/mongo/client/replica_set_monitor_integration_test.cpp
diff options
context:
space:
mode:
authorAndrew Shuvalov <andrew.shuvalov@mongodb.com>2021-05-21 16:07:01 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-21 16:46:27 +0000
commitf25468750488f8445794805873df5de456d9c557 (patch)
tree53e70931f760fc2b64b1b4b833b9ee6c0b2fcddb /src/mongo/client/replica_set_monitor_integration_test.cpp
parent2cb0ba6b43491c2aa564b6d93a5612132d69549e (diff)
downloadmongo-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.cpp32
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