summaryrefslogtreecommitdiff
path: root/src/mongo/db/concurrency
diff options
context:
space:
mode:
authorDianna Hohensee <dianna.hohensee@mongodb.com>2021-06-14 21:41:37 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-06-21 14:20:22 +0000
commita260a07648a984acaa54ab8cb1d18b37434d1b97 (patch)
tree4f543f170d179479adb4d8b5da43a98562ba2861 /src/mongo/db/concurrency
parentfaec09dbc6bb19cf0e2e457c9c11258460be7f11 (diff)
downloadmongo-a260a07648a984acaa54ab8cb1d18b37434d1b97.tar.gz
SERVER-57360 Log additional debug info for invariant(_requests.empty()) in ~LockerImpl
Diffstat (limited to 'src/mongo/db/concurrency')
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp20
-rw-r--r--src/mongo/db/concurrency/lock_state.h5
-rw-r--r--src/mongo/db/concurrency/lock_state_test.cpp19
3 files changed, 44 insertions, 0 deletions
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp
index 793a2a2dd7d..cd781a0cc40 100644
--- a/src/mongo/db/concurrency/lock_state.cpp
+++ b/src/mongo/db/concurrency/lock_state.cpp
@@ -230,6 +230,21 @@ void LockerImpl::dump() const {
"requests"_attr = entries);
}
+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();
+ LOGV2_ERROR(5736000, "Operation ending while holding locks.", "LockInfo"_attr = lockInfo);
+}
+
//
// CondVarLockGrantNotification
@@ -311,7 +326,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 d29f7817079..54a492ec99f 100644
--- a/src/mongo/db/concurrency/lock_state.h
+++ b/src/mongo/db/concurrency/lock_state.h
@@ -317,6 +317,11 @@ private:
void _setWaitingResource(ResourceId resId);
+ /**
+ * 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 8a8db4217f5..b7dac6c19a8 100644
--- a/src/mongo/db/concurrency/lock_state_test.cpp
+++ b/src/mongo/db/concurrency/lock_state_test.cpp
@@ -41,6 +41,7 @@
#include "mongo/db/service_context_test_fixture.h"
#include "mongo/transport/session.h"
#include "mongo/transport/transport_layer_mock.h"
+#include "mongo/unittest/death_test.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/fail_point.h"
#include "mongo/util/timer.h"
@@ -1216,4 +1217,22 @@ 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.") {
+ auto opCtx = makeOperationContext();
+
+ const ResourceId resId(RESOURCE_COLLECTION, "TestDB.collection"_sd);
+
+ LockerImpl locker;
+ locker.lockGlobal(opCtx.get(), 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