summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Caimano <ben.caimano@10gen.com>2018-06-05 16:35:49 -0400
committerBen Caimano <ben.caimano@10gen.com>2018-11-20 11:55:33 -0500
commitae4011cf301665046c435c18fd6ef088f5881e04 (patch)
tree2d08d44d091e1f800f5d2ae13d866c056903e307 /src
parent8edee17cf7c525a34194ce6ab8c9217ae651b829 (diff)
downloadmongo-ae4011cf301665046c435c18fd6ef088f5881e04.tar.gz
SERVER-34770 Retry on JavaScript execution interruptions in stepdown suites
(cherry picked from commit bb2de3700ee5b8eec9aa51cdbd2ecec937480c6c)
Diffstat (limited to 'src')
-rw-r--r--src/mongo/scripting/mozjs/implscope.cpp56
-rw-r--r--src/mongo/scripting/mozjs/implscope.h4
2 files changed, 36 insertions, 24 deletions
diff --git a/src/mongo/scripting/mozjs/implscope.cpp b/src/mongo/scripting/mozjs/implscope.cpp
index 0668d6d582b..13eaa312047 100644
--- a/src/mongo/scripting/mozjs/implscope.cpp
+++ b/src/mongo/scripting/mozjs/implscope.cpp
@@ -186,8 +186,18 @@ void MozJSImplScope::unregisterOperation() {
void MozJSImplScope::kill() {
{
- std::unique_lock<std::mutex> lk(_sleepMutex);
- _pendingKill.store(true);
+ stdx::lock_guard<stdx::mutex> lk(_mutex);
+
+ // If we are on the right thread, in the middle of an operation, and we have a registered
+ // opCtx, then we should check the opCtx for interrupts.
+ if (_mr._thread.get() == PR_GetCurrentThread() && _inOp > 0 && _opCtx) {
+ _killStatus = _opCtx->checkForInterruptNoAssert();
+ }
+
+ // If we didn't have a kill status, someone is killing us by hand here.
+ if (_killStatus.isOK()) {
+ _killStatus = Status(ErrorCodes::Interrupted, "JavaScript execution interrupted");
+ }
}
_sleepCondition.notify_all();
JS_RequestInterruptCallback(_runtime);
@@ -198,7 +208,8 @@ void MozJSImplScope::interrupt() {
}
bool MozJSImplScope::isKillPending() const {
- return _pendingKill.load();
+ stdx::lock_guard<stdx::mutex> lk(_mutex);
+ return !_killStatus.isOK();
}
OperationContext* MozJSImplScope::getOpContext() const {
@@ -222,21 +233,19 @@ bool MozJSImplScope::_interruptCallback(JSContext* cx) {
JS_MaybeGC(cx);
}
+ // Check our initial kill status (which might be fine).
+ auto status = [&scope]() -> Status {
+ stdx::lock_guard<stdx::mutex> lk(scope->_mutex);
+ return scope->_killStatus;
+ }();
+
if (scope->_hasOutOfMemoryException) {
- scope->_status = Status(ErrorCodes::JSInterpreterFailure, "Out of memory");
- } else if (scope->isKillPending()) {
- scope->_status = Status(ErrorCodes::Interrupted, "JavaScript execution interrupted");
- }
- // If we are on the right thread, in the middle of an operation, and we have a registered opCtx,
- // then we should check the opCtx for interrupts.
- if ((scope->_mr._thread.get() == PR_GetCurrentThread()) && (scope->_inOp > 0) &&
- scope->_opCtx) {
- auto status = scope->_opCtx->checkForInterruptNoAssert();
- if (!status.isOK()) {
- scope->_status = status;
- }
+ status = Status(ErrorCodes::JSInterpreterFailure, "Out of memory");
}
+ if (!status.isOK())
+ scope->setStatus(std::move(status));
+
if (!scope->_status.isOK()) {
scope->_engine->getDeadlineMonitor().stopDeadline(scope);
scope->unregisterOperation();
@@ -406,7 +415,7 @@ MozJSImplScope::MozJSImplScope(MozJSScriptEngine* engine)
_global(_globalProto.getProto()),
_funcs(),
_internedStrings(_context),
- _pendingKill(false),
+ _killStatus(Status::OK()),
_opId(0),
_opCtx(nullptr),
_inOp(0),
@@ -783,12 +792,12 @@ void MozJSImplScope::gc() {
}
void MozJSImplScope::sleep(Milliseconds ms) {
- std::unique_lock<std::mutex> lk(_sleepMutex);
+ stdx::unique_lock<stdx::mutex> lk(_mutex);
uassert(ErrorCodes::JSUncatchableError,
"sleep was interrupted by kill",
!_sleepCondition.wait_for(
- lk, ms.toSystemDuration(), [this] { return _pendingKill.load(); }));
+ lk, ms.toSystemDuration(), [this] { return !_killStatus.isOK(); }));
}
void MozJSImplScope::localConnectForDbEval(OperationContext* opCtx, const char* dbName) {
@@ -848,7 +857,7 @@ void MozJSImplScope::externalSetup() {
void MozJSImplScope::reset() {
unregisterOperation();
- _pendingKill.store(false);
+ _killStatus = Status::OK();
_pendingGC.store(false);
_requireOwnedObjects = false;
advanceGeneration();
@@ -897,9 +906,12 @@ void MozJSImplScope::setStatus(Status status) {
}
bool MozJSImplScope::_checkErrorState(bool success, bool reportError, bool assertOnError) {
- if (isKillPending()) {
- success = false;
- _status = Status(ErrorCodes::Interrupted, "JavaScript execution interrupted");
+ {
+ stdx::lock_guard<stdx::mutex> lk(_mutex);
+ if (!_killStatus.isOK()) {
+ success = false;
+ setStatus(_killStatus);
+ }
}
if (success) {
diff --git a/src/mongo/scripting/mozjs/implscope.h b/src/mongo/scripting/mozjs/implscope.h
index 2fe02d1af43..9ae68ac3366 100644
--- a/src/mongo/scripting/mozjs/implscope.h
+++ b/src/mongo/scripting/mozjs/implscope.h
@@ -411,8 +411,8 @@ private:
JS::HandleObject _global;
std::vector<JS::PersistentRootedValue> _funcs;
InternedStringTable _internedStrings;
- std::atomic<bool> _pendingKill;
- std::mutex _sleepMutex;
+ Status _killStatus;
+ mutable std::mutex _mutex;
std::condition_variable _sleepCondition;
std::string _error;
unsigned int _opId; // op id for this scope