diff options
| author | Huayu Ouyang <huayu.ouyang@mongodb.com> | 2023-08-17 20:31:27 +0000 |
|---|---|---|
| committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-08-22 19:31:47 +0000 |
| commit | 6a7b78cb8be6aed79e4f9889c76a91e1621bf482 (patch) | |
| tree | 67b406b956c0d6836fa7a5b31c09c17550d55e6d | |
| parent | 55d7ac73a0ce97785266ca48e721028aa24420b3 (diff) | |
SERVER-79950 Fix commitPreparedTransaction to not be interruptible in commitSplitTxn and reacquireTicket
(cherry picked from commit c58b294f49569ef72d782b9571ec7135839b58a9)
| -rw-r--r-- | src/mongo/db/concurrency/lock_state.cpp | 5 | ||||
| -rw-r--r-- | src/mongo/db/transaction/transaction_participant.cpp | 9 |
2 files changed, 13 insertions, 1 deletions
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp index 78ebf7c0385..c14bb6c2f4e 100644 --- a/src/mongo/db/concurrency/lock_state.cpp +++ b/src/mongo/db/concurrency/lock_state.cpp @@ -361,7 +361,10 @@ void LockerImpl::reacquireTicket(OperationContext* opCtx) { do { for (auto it = _requests.begin(); it; it.next()) { invariant(it->mode == LockMode::MODE_IS || it->mode == LockMode::MODE_IX); - opCtx->checkForInterrupt(); + // TODO SERVER-80206: Remove opCtx->checkForInterrupt(). + if (!_uninterruptibleLocksRequested) { + opCtx->checkForInterrupt(); + } // If we've reached this point then that means we tried to acquire a ticket but were // unsuccessful, implying that tickets are currently exhausted. Additionally, since diff --git a/src/mongo/db/transaction/transaction_participant.cpp b/src/mongo/db/transaction/transaction_participant.cpp index 9145f3c5cbf..105cec0b64e 100644 --- a/src/mongo/db/transaction/transaction_participant.cpp +++ b/src/mongo/db/transaction/transaction_participant.cpp @@ -2045,6 +2045,15 @@ void TransactionParticipant::Participant::_commitSplitPreparedTxnOnPrimary( TransactionParticipant::get(splitOpCtx.get()); newTxnParticipant.beginOrContinueTransactionUnconditionally( splitOpCtx.get(), {*(splitOpCtx->getTxnNumber())}); + + // This function is called while userOpCtx's lockState is under an UninterruptibleLockGuard, + // because once entering "committing with prepare" we cannot throw an exception, and + // therefore our lock acquisitions cannot be interruptible. We need to set an + // UninterruptibleLockGuard on newTxnParticipant's locker (this will be swapped into + // splitOpCtx's locker in unstashTransactionResources) in order to prevent the split + // transaction's lock acquisitions from being interruptible. + UninterruptibleLockGuard noInterrupt( // NOLINT + newTxnParticipant.o().txnResourceStash->locker()); // NOLINT newTxnParticipant.unstashTransactionResources(splitOpCtx.get(), "commitTransaction"); splitOpCtx->recoveryUnit()->setCommitTimestamp(commitTimestamp); |
