diff options
author | Matthew Russotto <matthew.russotto@mongodb.com> | 2022-02-10 11:11:41 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-02-10 17:40:45 +0000 |
commit | d8ff665343ad29cf286ee2cf4a1960d29371937b (patch) | |
tree | 132cda0c3339655dd8cff29d26a92937a12c29e4 /src/mongo/db/operation_context_test.cpp | |
parent | 482d143fdff542e67b7aa2a2d9e7c4468d1ecd28 (diff) | |
download | mongo-d8ff665343ad29cf286ee2cf4a1960d29371937b.tar.gz |
SERVER-63143 Operation can be interrupted by maxTimeMS timeout while waiting for lock even if _ignoreInterruptsExceptForReplStateChange is set
Diffstat (limited to 'src/mongo/db/operation_context_test.cpp')
-rw-r--r-- | src/mongo/db/operation_context_test.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/mongo/db/operation_context_test.cpp b/src/mongo/db/operation_context_test.cpp index 66fcda8632a..6850bc61f03 100644 --- a/src/mongo/db/operation_context_test.cpp +++ b/src/mongo/db/operation_context_test.cpp @@ -737,6 +737,74 @@ TEST_F(OperationDeadlineTests, DuringWaitMaxTimeExpirationDominatesUntilExpirati ASSERT_TRUE(opCtx->getCancellationToken().isCanceled()); } +TEST_F(OperationDeadlineTests, + MaxTimeExpirationIgnoredWhenIgnoringInterruptsExceptReplStateChange) { + auto opCtx = client->makeOperationContext(); + opCtx->setDeadlineByDate(mockClock->now(), ErrorCodes::MaxTimeMSExpired); + auto m = MONGO_MAKE_LATCH(); + stdx::condition_variable cv; + stdx::unique_lock<Latch> lk(m); + ASSERT_FALSE(opCtx->getCancellationToken().isCanceled()); + opCtx->setIgnoreInterruptsExceptForReplStateChange(true); + // Advance the clock so the MaxTimeMS is hit before the timeout. + mockClock->advance(Milliseconds(100)); + ASSERT_FALSE( + opCtx->waitForConditionOrInterruptUntil(cv, lk, mockClock->now(), [] { return false; })); + ASSERT_FALSE(opCtx->getCancellationToken().isCanceled()); +} + +TEST_F(OperationDeadlineTests, + AlreadyExpiredMaxTimeIgnoredWhenIgnoringInterruptsExceptReplStateChange) { + auto opCtx = client->makeOperationContext(); + opCtx->setDeadlineByDate(mockClock->now(), ErrorCodes::MaxTimeMSExpired); + auto m = MONGO_MAKE_LATCH(); + stdx::condition_variable cv; + stdx::unique_lock<Latch> lk(m); + ASSERT_FALSE(opCtx->getCancellationToken().isCanceled()); + ASSERT_THROWS_CODE(opCtx->waitForConditionOrInterruptUntil( + cv, lk, mockClock->now() + Seconds(1), [] { return false; }), + DBException, + ErrorCodes::MaxTimeMSExpired); + + ASSERT_EQ(ErrorCodes::MaxTimeMSExpired, opCtx->checkForInterruptNoAssert()); + ASSERT_TRUE(opCtx->getCancellationToken().isCanceled()); + opCtx->setIgnoreInterruptsExceptForReplStateChange(true); + ASSERT_OK(opCtx->checkForInterruptNoAssert()); + // Advance the clock so the MaxTimeMS is hit before the timeout. + mockClock->advance(Milliseconds(100)); + ASSERT_FALSE( + opCtx->waitForConditionOrInterruptUntil(cv, lk, mockClock->now(), [] { return false; })); + ASSERT_TRUE(opCtx->getCancellationToken().isCanceled()); +} + +TEST_F(OperationDeadlineTests, + MaxTimeRespectedAfterReplStateChangeWhenIgnoringInterruptsExceptReplStateChange) { + auto opCtx = client->makeOperationContext(); + opCtx->setDeadlineByDate(mockClock->now(), ErrorCodes::MaxTimeMSExpired); + auto m = MONGO_MAKE_LATCH(); + stdx::condition_variable cv; + stdx::unique_lock<Latch> lk(m); + ASSERT_FALSE(opCtx->getCancellationToken().isCanceled()); + ASSERT_THROWS_CODE(opCtx->waitForConditionOrInterruptUntil( + cv, lk, mockClock->now() + Seconds(1), [] { return false; }), + DBException, + ErrorCodes::MaxTimeMSExpired); + + ASSERT_EQ(ErrorCodes::MaxTimeMSExpired, opCtx->checkForInterruptNoAssert()); + ASSERT_TRUE(opCtx->getCancellationToken().isCanceled()); + opCtx->setIgnoreInterruptsExceptForReplStateChange(true); + ASSERT_OK(opCtx->checkForInterruptNoAssert()); + opCtx->markKilled(ErrorCodes::InterruptedDueToReplStateChange); + ASSERT_EQ(ErrorCodes::MaxTimeMSExpired, opCtx->checkForInterruptNoAssert()); + // Advance the clock so the MaxTimeMS is hit before the timeout. + mockClock->advance(Milliseconds(100)); + ASSERT_THROWS_CODE( + opCtx->waitForConditionOrInterruptUntil(cv, lk, mockClock->now(), [] { return false; }), + DBException, + ErrorCodes::MaxTimeMSExpired); + ASSERT_TRUE(opCtx->getCancellationToken().isCanceled()); +} + class ThreadedOperationDeadlineTests : public OperationDeadlineTests { public: using CvPred = std::function<bool()>; |