diff options
Diffstat (limited to 'src/mongo/db/introspect.cpp')
-rw-r--r-- | src/mongo/db/introspect.cpp | 28 |
1 files changed, 8 insertions, 20 deletions
diff --git a/src/mongo/db/introspect.cpp b/src/mongo/db/introspect.cpp index 78ae238a239..8bda2543426 100644 --- a/src/mongo/db/introspect.cpp +++ b/src/mongo/db/introspect.cpp @@ -50,9 +50,9 @@ namespace mongo { +using std::unique_ptr; using std::endl; using std::string; -using std::unique_ptr; namespace { @@ -117,32 +117,20 @@ void profile(OperationContext* opCtx, NetworkOp op) { const string dbName(nsToDatabase(CurOp::get(opCtx)->getNS())); - // True if we need to acquire an X lock on the database in order to create the system.profile - // collection. - bool acquireDbXLock = false; - try { - // 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. + // 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()) { - opCtx->setIgnoreInterruptsExceptForReplStateChange(true); + noInterrupt.emplace(opCtx->lockState()); } - // IX lock acquisitions beyond this block will not be related to writes to system.profile. - ON_BLOCK_EXIT([opCtx] { opCtx->setIgnoreInterruptsExceptForReplStateChange(false); }); - + bool acquireDbXLock = false; while (true) { std::unique_ptr<AutoGetDb> autoGetDb; if (acquireDbXLock) { - // We should not attempt to acquire an X lock while opCtx ignores interrupts. - opCtx->setIgnoreInterruptsExceptForReplStateChange(false); - autoGetDb.reset(new AutoGetDb(opCtx, dbName, MODE_X)); if (autoGetDb->getDb()) { createProfileCollection(opCtx, autoGetDb->getDb()).transitional_ignore(); |