summaryrefslogtreecommitdiff
path: root/src/mongo/db/introspect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/introspect.cpp')
-rw-r--r--src/mongo/db/introspect.cpp28
1 files changed, 16 insertions, 12 deletions
diff --git a/src/mongo/db/introspect.cpp b/src/mongo/db/introspect.cpp
index bc3232f31a2..f63cffbd86c 100644
--- a/src/mongo/db/introspect.cpp
+++ b/src/mongo/db/introspect.cpp
@@ -89,21 +89,25 @@ void profile(OperationContext* opCtx, NetworkOp op) {
// replication lag. As such, they should be excluded from Flow Control.
opCtx->setShouldParticipateInFlowControl(false);
+ // Set the opCtx to be only interruptible for replication state changes. This is needed
+ // because for some operations that are already marked as killed due to errors such as
+ // operation time exceeding maxTimeMS, we still want to output the profiler entry. Thus
+ // in these cases we do not interrupt lock acquisition even though the opCtx has already
+ // been killed. In the meantime we need to make sure replication state changes can still
+ // interrupt lock acquisition, otherwise there could be deadlocks when the state change
+ // thread is waiting for the session checked out by this opCtx while holding RSTL lock.
+ // However when maxLockTimeout is set, we want it to be always interruptible.
+ if (!opCtx->lockState()->hasMaxLockTimeout()) {
+ opCtx->setIgnoreInterruptsExceptForReplStateChange(true);
+ }
+
// IX lock acquisitions beyond this block will not be related to writes to system.profile.
- ON_BLOCK_EXIT(
- [opCtx, origFlowControl] { opCtx->setShouldParticipateInFlowControl(origFlowControl); });
+ ON_BLOCK_EXIT([opCtx, origFlowControl] {
+ opCtx->setIgnoreInterruptsExceptForReplStateChange(false);
+ opCtx->setShouldParticipateInFlowControl(origFlowControl);
+ });
try {
-
- // Even if the operation we are profiling was interrupted, we still want to output the
- // profiler entry. This lock guard will prevent lock acquisitions from throwing exceptions
- // before we finish writing the entry. However, our maximum lock timeout overrides
- // uninterruptibility.
- boost::optional<UninterruptibleLockGuard> noInterrupt;
- if (!opCtx->lockState()->hasMaxLockTimeout()) {
- noInterrupt.emplace(opCtx->lockState());
- }
-
const auto dbProfilingNS = NamespaceString(dbName, "system.profile");
AutoGetCollection autoColl(opCtx, dbProfilingNS, MODE_IX);
Database* const db = autoColl.getDb();