summaryrefslogtreecommitdiff
path: root/src/mongo/executor
diff options
context:
space:
mode:
authorJason Carey <jcarey@argv.me>2016-02-19 15:30:41 -0500
committerJason Carey <jcarey@argv.me>2016-02-19 16:42:54 -0500
commit401ad1915d6b7edde97c290f82cecab4a26880df (patch)
treeed421e088dcbab4fa9863d4706506d0bd1eea46e /src/mongo/executor
parent1d982f5421e93c7a59dab2d7acd5b549ab19790e (diff)
downloadmongo-401ad1915d6b7edde97c290f82cecab4a26880df.tar.gz
SERVER-22768 fix ASIO cancelled to cancelled
When operations transition from kCancelled to kCancelled, as when an operation is cancel()ed twice, an invariant fires. We should handle that case specially and treat the transition as a noop.
Diffstat (limited to 'src/mongo/executor')
-rw-r--r--src/mongo/executor/network_interface_asio.h3
-rw-r--r--src/mongo/executor/network_interface_asio_operation.cpp14
2 files changed, 16 insertions, 1 deletions
diff --git a/src/mongo/executor/network_interface_asio.h b/src/mongo/executor/network_interface_asio.h
index 441e89aceb0..3a175830dc8 100644
--- a/src/mongo/executor/network_interface_asio.h
+++ b/src/mongo/executor/network_interface_asio.h
@@ -30,6 +30,7 @@
#include <asio.hpp>
+#include <array>
#include <boost/optional.hpp>
#include <memory>
#include <string>
@@ -424,7 +425,7 @@ private:
* We hold an array of states to show the path this AsyncOp has taken.
* Must be holding the access control's lock to edit.
*/
- State _states[kMaxStateTransitions];
+ std::array<State, kMaxStateTransitions> _states;
};
void _startCommand(AsyncOp* op);
diff --git a/src/mongo/executor/network_interface_asio_operation.cpp b/src/mongo/executor/network_interface_asio_operation.cpp
index 6919a9b8b50..813ff51dd09 100644
--- a/src/mongo/executor/network_interface_asio_operation.cpp
+++ b/src/mongo/executor/network_interface_asio_operation.cpp
@@ -371,6 +371,20 @@ void NetworkInterfaceASIO::AsyncOp::_transitionToState_inlock(AsyncOp::State new
return;
}
+ // We can transition to cancelled multiple times if cancel() is called
+ // multiple times. Ignore that transition if we're already cancelled.
+ if (newState == State::kCanceled) {
+ // Find the current state
+ auto iter = std::find_if_not(_states.rbegin(),
+ _states.rend(),
+ [](const State& state) { return state == State::kNoState; });
+
+ // If its cancelled, just return
+ if (iter != _states.rend() && *iter == State::kCanceled) {
+ return;
+ }
+ }
+
for (int i = 0; i < kMaxStateTransitions; i++) {
// We can't transition to the same state twice.
MONGO_ASYNC_OP_INVARIANT(_states[i] != newState,