diff options
author | Jonathan Reams <jbreams@mongodb.com> | 2016-08-25 15:58:25 -0400 |
---|---|---|
committer | Jonathan Reams <jbreams@mongodb.com> | 2017-05-04 15:26:27 -0400 |
commit | 317a3f627be5adf149d857a248d344342897e5f9 (patch) | |
tree | 385aaf653eb1148062e22fcaae872c8bbf69b341 | |
parent | 4b949cc2b4bfb240f1fc67a500fc86de520fdf06 (diff) | |
download | mongo-317a3f627be5adf149d857a248d344342897e5f9.tar.gz |
SERVER-25764 Interrupt javascript periodically.
(cherry picked from commit 1875792bdc435c695aca1b6b57be7486e7df70c5)
-rw-r--r-- | src/mongo/scripting/deadline_monitor.h | 30 | ||||
-rw-r--r-- | src/mongo/scripting/deadline_monitor_test.cpp | 1 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/implscope.cpp | 18 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/implscope.h | 2 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/proxyscope.cpp | 4 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/proxyscope.h | 2 |
6 files changed, 45 insertions, 12 deletions
diff --git a/src/mongo/scripting/deadline_monitor.h b/src/mongo/scripting/deadline_monitor.h index 89f7e9d1b84..c4923e4aab9 100644 --- a/src/mongo/scripting/deadline_monitor.h +++ b/src/mongo/scripting/deadline_monitor.h @@ -91,11 +91,18 @@ public: * @param task the task to kill() * @param timeoutMs number of milliseconds before the deadline expires */ - void startDeadline(_Task* const task, uint64_t timeoutMs) { - const auto deadline = Date_t::now() + Milliseconds(timeoutMs); + void startDeadline(_Task* const task, int64_t timeoutMs) { + Date_t deadline; + if (timeoutMs > 0) { + deadline = Date_t::now() + Milliseconds(timeoutMs); + } else { + deadline = Date_t::max(); + } stdx::lock_guard<stdx::mutex> lk(_deadlineMutex); - _tasks[task] = deadline; + if (_tasks.find(task) == _tasks.end()) { + _tasks.emplace(task, deadline); + } if (deadline < _nearestDeadlineWallclock) { _nearestDeadlineWallclock = deadline; @@ -121,14 +128,16 @@ private: */ void deadlineMonitorThread() { stdx::unique_lock<stdx::mutex> lk(_deadlineMutex); + Date_t lastInterruptCycle = Date_t::now(); while (!_inShutdown) { // get the next interval to wait const Date_t now = Date_t::now(); // wait for a task to be added or a deadline to expire if (_nearestDeadlineWallclock > now) { - if (_nearestDeadlineWallclock == Date_t::max()) { - _newDeadlineAvailable.wait(lk); + if (_nearestDeadlineWallclock == Date_t::max() || + _nearestDeadlineWallclock - now > Seconds{1}) { + _newDeadlineAvailable.wait_for(lk, Seconds{1}); } else { _newDeadlineAvailable.wait_until(lk, _nearestDeadlineWallclock.toSystemTimePoint()); @@ -138,7 +147,7 @@ private: // set the next interval to wait for deadline completion _nearestDeadlineWallclock = Date_t::max(); - typename TaskDeadlineMap::iterator i = _tasks.begin(); + auto i = _tasks.begin(); while (i != _tasks.end()) { if (i->second < now) { // deadline expired @@ -152,10 +161,17 @@ private: ++i; } } + + if (now - lastInterruptCycle > Seconds{1}) { + for (auto it : _tasks) { + it.first->interrupt(); + } + lastInterruptCycle = now; + } } } - typedef unordered_map<_Task*, Date_t> TaskDeadlineMap; + using TaskDeadlineMap = std::unordered_map<_Task*, Date_t>; TaskDeadlineMap _tasks; // map of running tasks with deadlines stdx::mutex _deadlineMutex; // protects all non-const members, except _monitorThread stdx::condition_variable _newDeadlineAvailable; // Signaled for timeout, start and stop diff --git a/src/mongo/scripting/deadline_monitor_test.cpp b/src/mongo/scripting/deadline_monitor_test.cpp index 98f4008b234..71daefbce8f 100644 --- a/src/mongo/scripting/deadline_monitor_test.cpp +++ b/src/mongo/scripting/deadline_monitor_test.cpp @@ -72,6 +72,7 @@ public: if (_group) _group->noteKill(); } + void interrupt() {} TaskGroup* _group; uint64_t _killed; }; diff --git a/src/mongo/scripting/mozjs/implscope.cpp b/src/mongo/scripting/mozjs/implscope.cpp index c5bd51ef5cd..70f76355202 100644 --- a/src/mongo/scripting/mozjs/implscope.cpp +++ b/src/mongo/scripting/mozjs/implscope.cpp @@ -169,6 +169,10 @@ void MozJSImplScope::kill() { JS_RequestInterruptCallback(_runtime); } +void MozJSImplScope::interrupt() { + JS_RequestInterruptCallback(_runtime); +} + bool MozJSImplScope::isKillPending() const { return _pendingKill.load(); } @@ -606,14 +610,16 @@ int MozJSImplScope::invoke(ScriptingFunction func, if (timeoutMs) _engine->getDeadlineMonitor().startDeadline(this, timeoutMs); + else { + _engine->getDeadlineMonitor().startDeadline(this, -1); + } JS::RootedValue out(_context); JS::RootedObject obj(_context, smrecv.toObjectOrNull()); bool success = JS::Call(_context, obj, funcValue, args, &out); - if (timeoutMs) - _engine->getDeadlineMonitor().stopDeadline(this); + _engine->getDeadlineMonitor().stopDeadline(this); _checkErrorState(success); @@ -651,15 +657,17 @@ bool MozJSImplScope::exec(StringData code, if (_checkErrorState(success, reportError, assertOnError)) return false; - if (timeoutMs) + if (timeoutMs) { _engine->getDeadlineMonitor().startDeadline(this, timeoutMs); + } else { + _engine->getDeadlineMonitor().startDeadline(this, -1); + } JS::RootedValue out(_context); success = JS_ExecuteScript(_context, _global, script, &out); - if (timeoutMs) - _engine->getDeadlineMonitor().stopDeadline(this); + _engine->getDeadlineMonitor().stopDeadline(this); if (_checkErrorState(success, reportError, assertOnError)) return false; diff --git a/src/mongo/scripting/mozjs/implscope.h b/src/mongo/scripting/mozjs/implscope.h index 3fac5e5bdef..48544aaf5b2 100644 --- a/src/mongo/scripting/mozjs/implscope.h +++ b/src/mongo/scripting/mozjs/implscope.h @@ -89,6 +89,8 @@ public: void kill(); + void interrupt(); + bool isKillPending() const override; OperationContext* getOpContext() const; diff --git a/src/mongo/scripting/mozjs/proxyscope.cpp b/src/mongo/scripting/mozjs/proxyscope.cpp index 5e48aabf9cf..2fd32ff6878 100644 --- a/src/mongo/scripting/mozjs/proxyscope.cpp +++ b/src/mongo/scripting/mozjs/proxyscope.cpp @@ -244,6 +244,10 @@ void MozJSProxyScope::kill() { _implScope->kill(); } +void MozJSProxyScope::interrupt() { + _implScope->interrupt(); +} + /** * Invokes a function on the implementation thread * diff --git a/src/mongo/scripting/mozjs/proxyscope.h b/src/mongo/scripting/mozjs/proxyscope.h index 09a84101dfd..d19e24149bd 100644 --- a/src/mongo/scripting/mozjs/proxyscope.h +++ b/src/mongo/scripting/mozjs/proxyscope.h @@ -175,6 +175,8 @@ public: */ void kill(); + void interrupt(); + private: template <typename Closure> void run(Closure&& closure); |