summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHuayu Ouyang <huayu.ouyang@mongodb.com>2023-08-17 20:31:27 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-08-22 19:31:47 +0000
commit6a7b78cb8be6aed79e4f9889c76a91e1621bf482 (patch)
tree67b406b956c0d6836fa7a5b31c09c17550d55e6d
parent55d7ac73a0ce97785266ca48e721028aa24420b3 (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.cpp5
-rw-r--r--src/mongo/db/transaction/transaction_participant.cpp9
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);