diff options
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/client.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/client.h | 16 | ||||
-rw-r--r-- | src/mongo/db/operation_context.cpp | 15 |
3 files changed, 35 insertions, 4 deletions
diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp index ec0283e0468..77204405f3c 100644 --- a/src/mongo/db/client.cpp +++ b/src/mongo/db/client.cpp @@ -183,6 +183,14 @@ bool Client::hasAnyActiveCurrentOp() const { return false; } +void Client::setKilled() noexcept { + stdx::lock_guard<Client> lk(*this); + _killed.store(true); + if (_opCtx) { + _serviceContext->killOperation(lk, _opCtx, ErrorCodes::ClientMarkedKilled); + } +} + ThreadClient::ThreadClient(ServiceContext* serviceContext) : ThreadClient(getThreadName(), serviceContext, nullptr) {} diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h index f98d17d5252..3ffed27adc2 100644 --- a/src/mongo/db/client.h +++ b/src/mongo/db/client.h @@ -41,6 +41,7 @@ #include "mongo/db/namespace_string.h" #include "mongo/db/service_context.h" +#include "mongo/platform/atomic_word.h" #include "mongo/platform/random.h" #include "mongo/stdx/thread.h" #include "mongo/transport/session.h" @@ -246,6 +247,19 @@ public: */ bool hasAnyActiveCurrentOp() const; + /** + * Signal the client's OperationContext that it has been killed. + * Any future OperationContext on this client will also receive a kill signal. + */ + void setKilled() noexcept; + + /** + * Get the state for killing the client's OperationContext. + */ + bool getKilled() const noexcept { + return _killed.loadRelaxed(); + } + private: friend class ServiceContext; friend class ThreadClient; @@ -275,6 +289,8 @@ private: bool _systemOperationKillable = false; PseudoRandom _prng; + + AtomicWord<bool> _killed{false}; }; /** diff --git a/src/mongo/db/operation_context.cpp b/src/mongo/db/operation_context.cpp index ee38faab01b..a0bee37b49b 100644 --- a/src/mongo/db/operation_context.cpp +++ b/src/mongo/db/operation_context.cpp @@ -203,10 +203,17 @@ bool opShouldFail(Client* client, const BSONObj& failPointInfo) { } // namespace Status OperationContext::checkForInterruptNoAssert() noexcept { - // TODO: Remove the MONGO_likely(getClient()) once all operation contexts are constructed with - // clients. - if (MONGO_likely(getClient() && getServiceContext()) && - getServiceContext()->getKillAllOperations() && !_isExecutingShutdown) { + // TODO: Remove the MONGO_likely(hasClientAndServiceContext) once all operation contexts are + // constructed with clients. + const auto hasClientAndServiceContext = getClient() && getServiceContext(); + + if (MONGO_likely(hasClientAndServiceContext) && getClient()->getKilled() && + !_isExecutingShutdown) { + return Status(ErrorCodes::ClientMarkedKilled, "client has been killed"); + } + + if (MONGO_likely(hasClientAndServiceContext) && getServiceContext()->getKillAllOperations() && + !_isExecutingShutdown) { return Status(ErrorCodes::InterruptedAtShutdown, "interrupted at shutdown"); } |