summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/replication_executor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/repl/replication_executor.cpp')
-rw-r--r--src/mongo/db/repl/replication_executor.cpp11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/mongo/db/repl/replication_executor.cpp b/src/mongo/db/repl/replication_executor.cpp
index 9fcf7b01359..cfdaa785b1a 100644
--- a/src/mongo/db/repl/replication_executor.cpp
+++ b/src/mongo/db/repl/replication_executor.cpp
@@ -414,7 +414,9 @@ void ReplicationExecutor::_doOperation(OperationContext* opCtx,
return;
Callback* callback = _getCallbackFromHandle(cbHandle);
const WorkQueue::iterator iter = callback->_iter;
+ callback->_isRemoved = true;
iter->callback = CallbackHandle();
+ iter->isNetworkOperation = false;
_freeQueue.splice(_freeQueue.begin(), *workQueue, iter);
lk.unlock();
{
@@ -481,7 +483,10 @@ ReplicationExecutor::getWork() {
}
const WorkItem work = *_readyQueue.begin();
const CallbackHandle cbHandle = work.callback;
+ Callback* callback = _getCallbackFromHandle(cbHandle);
+ callback->_isRemoved = true;
_readyQueue.begin()->callback = CallbackHandle();
+ _readyQueue.begin()->isNetworkOperation = false;
_freeQueue.splice(_freeQueue.begin(), _readyQueue, _readyQueue.begin());
return std::make_pair(work, cbHandle);
}
@@ -582,6 +587,7 @@ ReplicationExecutor::Callback::Callback(ReplicationExecutor* executor,
_callbackFn(callbackFn),
_isCanceled(false),
_isSleeper(false),
+ _isRemoved(false),
_iter(iter),
_finishedEvent(finishedEvent) {}
@@ -594,6 +600,11 @@ bool ReplicationExecutor::Callback::isCanceled() const {
void ReplicationExecutor::Callback::cancel() {
stdx::unique_lock<stdx::mutex> lk(_executor->_mutex);
+ // If this element has already been removed from the queues,
+ // the cancel is too late and has no effect.
+ if (_isRemoved)
+ return;
+
_isCanceled = true;
if (_isSleeper) {