summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatt Kneiser <matt.kneiser@mongodb.com>2023-03-29 00:06:27 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-03-29 21:14:18 +0000
commit62488ce91951aaf0ac35df145779778219261c0a (patch)
tree72d66df4c7597c8c09efe8d0d0dcc53b5d21a75f /src
parentea7276ff7a715ac6e6f2a42797ca57aa6de3572a (diff)
downloadmongo-62488ce91951aaf0ac35df145779778219261c0a.tar.gz
SERVER-75205 Fix deadlock involving FCV lock
With minor jstest amendments. (cherry picked from commit e74f9c2fdf73ad707419fa4a8ae57aec70423ca6)
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp14
1 files changed, 12 insertions, 2 deletions
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp
index 8f60fec8c5a..8a0bf755d9e 100644
--- a/src/mongo/db/concurrency/lock_state.cpp
+++ b/src/mongo/db/concurrency/lock_state.cpp
@@ -839,13 +839,21 @@ void LockerImpl::restoreLockState(OperationContext* opCtx, const Locker::LockSna
getFlowControlTicket(opCtx, state.globalMode);
std::vector<OneLock>::const_iterator it = state.locks.begin();
- // If we locked the PBWM, it must be locked before the resourceIdGlobal and
- // resourceIdReplicationStateTransitionLock resources.
+ // If we locked the PBWM, it must be locked before the
+ // resourceIdFeatureCompatibilityVersion, resourceIdReplicationStateTransitionLock, and
+ // resourceIdGlobal resources.
if (it != state.locks.end() && it->resourceId == resourceIdParallelBatchWriterMode) {
lock(opCtx, it->resourceId, it->mode);
it++;
}
+ // If we locked the FCV lock, it must be locked before the
+ // resourceIdReplicationStateTransitionLock and resourceIdGlobal resources.
+ if (it != state.locks.end() && it->resourceId == resourceIdFeatureCompatibilityVersion) {
+ lock(opCtx, it->resourceId, it->mode);
+ it++;
+ }
+
// If we locked the RSTL, it must be locked before the resourceIdGlobal resource.
if (it != state.locks.end() && it->resourceId == resourceIdReplicationStateTransitionLock) {
lock(opCtx, it->resourceId, it->mode);
@@ -854,6 +862,8 @@ void LockerImpl::restoreLockState(OperationContext* opCtx, const Locker::LockSna
lockGlobal(opCtx, state.globalMode);
for (; it != state.locks.end(); it++) {
+ // Ensures we don't acquire locks out of order which can lead to deadlock.
+ invariant(it->resourceId.getType() != ResourceType::RESOURCE_GLOBAL);
lock(opCtx, it->resourceId, it->mode);
}
invariant(_modeForTicket != MODE_NONE);