diff options
author | Matt Kneiser <matt.kneiser@mongodb.com> | 2023-03-29 00:06:27 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-03-29 21:14:18 +0000 |
commit | 62488ce91951aaf0ac35df145779778219261c0a (patch) | |
tree | 72d66df4c7597c8c09efe8d0d0dcc53b5d21a75f /src/mongo/db/concurrency | |
parent | ea7276ff7a715ac6e6f2a42797ca57aa6de3572a (diff) | |
download | mongo-62488ce91951aaf0ac35df145779778219261c0a.tar.gz |
SERVER-75205 Fix deadlock involving FCV lock
With minor jstest amendments.
(cherry picked from commit e74f9c2fdf73ad707419fa4a8ae57aec70423ca6)
Diffstat (limited to 'src/mongo/db/concurrency')
-rw-r--r-- | src/mongo/db/concurrency/lock_state.cpp | 14 |
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); |