diff options
author | Justin Seyster <justin.seyster@mongodb.com> | 2018-03-30 15:25:47 -0400 |
---|---|---|
committer | Justin Seyster <justin.seyster@mongodb.com> | 2018-04-12 16:05:53 -0400 |
commit | bc19d43fdc4aab85264def96f638128c0ddb8483 (patch) | |
tree | 09b5a9a15982edd4998d4665d6c67f8fbd7c83e7 /src/mongo/db/ops | |
parent | c6620182aebd1b62d31879ce4d9456ff197aea22 (diff) | |
download | mongo-bc19d43fdc4aab85264def96f638128c0ddb8483.tar.gz |
SERVER-27534 All writing operations must fail if the term changes.
The description of this SERVER ticket describes a nasty race that can
occur if elections happen inbetween two batches during a large
update. (The included test confirms that the race is possible.)
To fix this, we want to check the operation context for interrupts
with each batch, and we need to make sure the check happens _after_
the collection lock gets taken and before the batch
inserts/updates/deletes execute.
A recent change to locking gives us almost exactly this for free: if a
collection lock has to wait, it throws an exception when the operation
context is interrupted, ending the operation. If the lock doesn't
wait, though, there is no check.
This patch adds that check in. Acquiring a lock now always throws if
the operation context is interrupted, which closes the race window in
this bug.
Diffstat (limited to 'src/mongo/db/ops')
-rw-r--r-- | src/mongo/db/ops/write_ops_exec.cpp | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/src/mongo/db/ops/write_ops_exec.cpp b/src/mongo/db/ops/write_ops_exec.cpp index 7152285fc0f..bfbeb06bc94 100644 --- a/src/mongo/db/ops/write_ops_exec.cpp +++ b/src/mongo/db/ops/write_ops_exec.cpp @@ -85,6 +85,7 @@ namespace { MONGO_FP_DECLARE(failAllInserts); MONGO_FP_DECLARE(failAllUpdates); MONGO_FP_DECLARE(failAllRemoves); +MONGO_FP_DECLARE(hangDuringBatchInsert); void updateRetryStats(OperationContext* opCtx, bool containsRetry) { if (containsRetry) { @@ -368,7 +369,9 @@ bool insertBatchAndHandleErrors(OperationContext* opCtx, boost::optional<AutoGetCollection> collection; auto acquireCollection = [&] { while (true) { - opCtx->checkForInterrupt(); + if (MONGO_FAIL_POINT(hangDuringBatchInsert)) { + MONGO_FAIL_POINT_PAUSE_WHILE_SET(hangDuringBatchInsert); + } if (MONGO_FAIL_POINT(failAllInserts)) { uasserted(ErrorCodes::InternalError, "failAllInserts failpoint active!"); @@ -606,7 +609,6 @@ static SingleWriteResult performSingleUpdateOp(OperationContext* opCtx, boost::optional<AutoGetCollection> collection; while (true) { - opCtx->checkForInterrupt(); if (MONGO_FAIL_POINT(failAllUpdates)) { uasserted(ErrorCodes::InternalError, "failAllUpdates failpoint active!"); } @@ -762,8 +764,6 @@ static SingleWriteResult performSingleDeleteOp(OperationContext* opCtx, ParsedDelete parsedDelete(opCtx, &request); uassertStatusOK(parsedDelete.parseRequest()); - opCtx->checkForInterrupt(); - if (MONGO_FAIL_POINT(failAllRemoves)) { uasserted(ErrorCodes::InternalError, "failAllRemoves failpoint active!"); } |