summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2016-03-11 14:23:56 -0500
committerBenety Goh <benety@mongodb.com>2016-03-15 10:19:24 -0400
commit65afd1db6fc3b6fdba053dc75117967d30d48feb (patch)
tree50db0942ae0705fb5f734bd5237e81c91cd00cb9
parentb8dec1f8d1849ab61b5075821f3ab4343aeecc7a (diff)
downloadmongo-65afd1db6fc3b6fdba053dc75117967d30d48feb.tar.gz
SERVER-23082 fixed race in ThreadPoolTaskExecutor between scheduleWorkAt() and cancel().
-rw-r--r--src/mongo/executor/thread_pool_task_executor.cpp19
1 files changed, 11 insertions, 8 deletions
diff --git a/src/mongo/executor/thread_pool_task_executor.cpp b/src/mongo/executor/thread_pool_task_executor.cpp
index 9b9660ca5a0..957129c7bd3 100644
--- a/src/mongo/executor/thread_pool_task_executor.cpp
+++ b/src/mongo/executor/thread_pool_task_executor.cpp
@@ -259,6 +259,9 @@ StatusWith<TaskExecutor::CallbackHandle> ThreadPoolTaskExecutor::scheduleWorkAt(
}
invariant(now() >= when);
stdx::unique_lock<stdx::mutex> lk(_mutex);
+ if (cbState->canceled.load()) {
+ return;
+ }
scheduleIntoPool_inlock(&_sleepersQueue, cbState->iter, std::move(lk));
});
@@ -457,20 +460,20 @@ void ThreadPoolTaskExecutor::scheduleIntoPool_inlock(WorkQueue* fromQueue,
}
void ThreadPoolTaskExecutor::runCallback(std::shared_ptr<CallbackState> cbStateArg) {
- auto cbStatePtr = cbStateArg.get();
CallbackHandle cbHandle;
- setCallbackForHandle(&cbHandle, std::move(cbStateArg));
+ setCallbackForHandle(&cbHandle, cbStateArg);
CallbackArgs args(this,
std::move(cbHandle),
- cbStatePtr->canceled.load()
+ cbStateArg->canceled.load()
? Status({ErrorCodes::CallbackCanceled, "Callback canceled"})
: Status::OK());
- cbStatePtr->callback(std::move(args));
- cbStatePtr->isFinished.store(true);
+ invariant(!cbStateArg->isFinished.load());
+ cbStateArg->callback(std::move(args));
+ cbStateArg->isFinished.store(true);
stdx::lock_guard<stdx::mutex> lk(_mutex);
- _poolInProgressQueue.erase(cbStatePtr->iter);
- if (cbStatePtr->finishedCondition) {
- cbStatePtr->finishedCondition->notify_all();
+ _poolInProgressQueue.erase(cbStateArg->iter);
+ if (cbStateArg->finishedCondition) {
+ cbStateArg->finishedCondition->notify_all();
}
}