diff options
author | Dianna Hohensee <dianna.hohensee@mongodb.com> | 2021-06-14 21:41:37 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-08-20 17:41:09 +0000 |
commit | 18315d2e163ce47d0d7ca7503961c4566e04d70a (patch) | |
tree | 6717195272f81dc8957a9beea7c433e50d916ab8 | |
parent | dcca76b8c10312a88ae4e6ae43c69cfbea0a1b1a (diff) | |
download | mongo-18315d2e163ce47d0d7ca7503961c4566e04d70a.tar.gz |
SERVER-57360 Log additional debug info for invariant(_requests.empty()) in ~LockerImpl
(cherry picked from commit a260a07648a984acaa54ab8cb1d18b37434d1b97)
-rw-r--r-- | src/mongo/db/concurrency/lock_state.cpp | 20 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_state.h | 5 | ||||
-rw-r--r-- | src/mongo/db/concurrency/lock_state_test.cpp | 17 | ||||
-rw-r--r-- | src/mongo/db/concurrency/locker_noop.h | 3 |
4 files changed, 44 insertions, 1 deletions
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp index b684416b445..0b4a5dce0c9 100644 --- a/src/mongo/db/concurrency/lock_state.cpp +++ b/src/mongo/db/concurrency/lock_state.cpp @@ -205,6 +205,21 @@ void LockerImpl::dump() const { log() << ss.str(); } +void LockerImpl::_dumpLockerAndLockManagerRequests() { + // Log the _requests that this locker holds. This will provide identifying information to cross + // reference with the LockManager dump below for extra information. + dump(); + + // Log the LockManager's lock information. Given the locker 'dump()' above, we should be able to + // easily cross reference to find the lock info matching this operation. The LockManager can + // safely access (under internal locks) the LockRequest data that the locker cannot. + BSONObjBuilder builder; + auto lockToClientMap = LockManager::getLockToClientMap(getGlobalServiceContext()); + getGlobalLockManager()->getLockInfoBSON(lockToClientMap, &builder); + auto lockInfo = builder.done(); + LOG(0) << "Operation ending while holding locks. LockInfo" << redact(lockInfo.toString()); +} + // // CondVarLockGrantNotification @@ -286,7 +301,12 @@ LockerImpl::~LockerImpl() { // to delete with unaccounted locks anyways. invariant(!inAWriteUnitOfWork()); invariant(_numResourcesToUnlockAtEndUnitOfWork == 0); + + if (!_requests.empty()) { + _dumpLockerAndLockManagerRequests(); + } invariant(_requests.empty()); + invariant(_modeForTicket == MODE_NONE); // Reset the locking statistics so the object can be reused diff --git a/src/mongo/db/concurrency/lock_state.h b/src/mongo/db/concurrency/lock_state.h index 386ea3aa196..dfa0e709d77 100644 --- a/src/mongo/db/concurrency/lock_state.h +++ b/src/mongo/db/concurrency/lock_state.h @@ -321,6 +321,11 @@ private: */ bool _acquireTicket(OperationContext* opCtx, LockMode mode, Date_t deadline); + /** + * Calls dump() on this locker instance and the lock manager. + */ + void _dumpLockerAndLockManagerRequests(); + // Used to disambiguate different lockers const LockerId _id; diff --git a/src/mongo/db/concurrency/lock_state_test.cpp b/src/mongo/db/concurrency/lock_state_test.cpp index 00297be4d37..35658b02284 100644 --- a/src/mongo/db/concurrency/lock_state_test.cpp +++ b/src/mongo/db/concurrency/lock_state_test.cpp @@ -39,6 +39,7 @@ #include "mongo/db/concurrency/lock_manager_test_help.h" #include "mongo/db/concurrency/locker.h" #include "mongo/db/service_context_test_fixture.h" +#include "mongo/unittest/death_test.h" #include "mongo/unittest/unittest.h" #include "mongo/util/fail_point_service.h" #include "mongo/util/log.h" @@ -1143,4 +1144,20 @@ TEST_F(LockerImplTest, ConvertLockPendingUnlockAndUnlock) { locker.unlockGlobal(); } +// This test exercises the lock dumping code in ~LockerImpl in case locks are held on destruction. +DEATH_TEST_F(LockerImplTest, + LocksHeldOnDestructionCausesALocksDump, + "Operation ending while holding locks.") { + const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd); + + LockerImpl locker; + locker.lockGlobal(MODE_IX); + locker.lock(resId, MODE_X); + + ASSERT(locker.isLockHeldForMode(resId, MODE_X)); + ASSERT(locker.isLockHeldForMode(resId, MODE_S)); + + // 'locker' destructor should invariant because locks are still held. +} + } // namespace mongo diff --git a/src/mongo/db/concurrency/locker_noop.h b/src/mongo/db/concurrency/locker_noop.h index 3780e4f5c0b..0dc626e7ec7 100644 --- a/src/mongo/db/concurrency/locker_noop.h +++ b/src/mongo/db/concurrency/locker_noop.h @@ -51,7 +51,8 @@ public: } virtual LockerId getId() const { - MONGO_UNREACHABLE; + // For unit testing. + return -7; } stdx::thread::id getThreadId() const override { |