summaryrefslogtreecommitdiff
path: root/src/mongo/scripting
diff options
context:
space:
mode:
authorJonathan Reams <jbreams@mongodb.com>2016-08-25 15:58:25 -0400
committerJonathan Reams <jbreams@mongodb.com>2016-08-29 17:15:34 -0400
commit1875792bdc435c695aca1b6b57be7486e7df70c5 (patch)
tree5251a72001f194e0599ceeb7d9bf4208f6c54b70 /src/mongo/scripting
parentbdf345a78764d2552373b5f938ac9aa6be5346b9 (diff)
downloadmongo-1875792bdc435c695aca1b6b57be7486e7df70c5.tar.gz
SERVER-25764 Interrupt javascript periodically.
Diffstat (limited to 'src/mongo/scripting')
-rw-r--r--src/mongo/scripting/deadline_monitor.h28
-rw-r--r--src/mongo/scripting/deadline_monitor_test.cpp1
-rw-r--r--src/mongo/scripting/mozjs/implscope.cpp18
-rw-r--r--src/mongo/scripting/mozjs/implscope.h2
-rw-r--r--src/mongo/scripting/mozjs/proxyscope.cpp4
-rw-r--r--src/mongo/scripting/mozjs/proxyscope.h2
6 files changed, 44 insertions, 11 deletions
diff --git a/src/mongo/scripting/deadline_monitor.h b/src/mongo/scripting/deadline_monitor.h
index d3c30f4b2e8..9a68b78e60f 100644
--- a/src/mongo/scripting/deadline_monitor.h
+++ b/src/mongo/scripting/deadline_monitor.h
@@ -93,10 +93,17 @@ public:
* @param timeoutMs number of milliseconds before the deadline expires
*/
void startDeadline(_Task* const task, int64_t timeoutMs) {
- const auto deadline = Date_t::now() + Milliseconds(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;
@@ -122,14 +129,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}.toSystemDuration());
} else {
_newDeadlineAvailable.wait_until(lk,
_nearestDeadlineWallclock.toSystemTimePoint());
@@ -139,7 +148,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
@@ -153,10 +162,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 c808a88875f..3a8fb1e2d18 100644
--- a/src/mongo/scripting/mozjs/implscope.cpp
+++ b/src/mongo/scripting/mozjs/implscope.cpp
@@ -179,6 +179,10 @@ void MozJSImplScope::kill() {
JS_RequestInterruptCallback(_runtime);
}
+void MozJSImplScope::interrupt() {
+ JS_RequestInterruptCallback(_runtime);
+}
+
bool MozJSImplScope::isKillPending() const {
return _pendingKill.load();
}
@@ -635,14 +639,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);
@@ -680,15 +686,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, 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 080716428ac..d34921578b7 100644
--- a/src/mongo/scripting/mozjs/implscope.h
+++ b/src/mongo/scripting/mozjs/implscope.h
@@ -90,6 +90,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 d5233f8379d..cf41e84091c 100644
--- a/src/mongo/scripting/mozjs/proxyscope.cpp
+++ b/src/mongo/scripting/mozjs/proxyscope.cpp
@@ -245,6 +245,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);