Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

deadline: feasibility study

Refs #2395.
  • Loading branch information...
commit ac358b1168e742e46277b2657a5748e18627d1f6 1 parent 76b1a38
koichik authored
View
37 src/node.cc
@@ -953,10 +953,13 @@ void MakeCallback(Handle<Object> object,
TryCatch try_catch;
+ Isolate* isolate = Isolate::GetCurrent();
+ isolate->BeginExecution(uv_now(isolate->GetLoop()) + 5000);
callback->Call(object, argc, argv);
+ bool terminated = isolate->EndExecution();
if (try_catch.HasCaught()) {
- FatalException(try_catch);
+ FatalException(try_catch, terminated);
}
}
@@ -1721,7 +1724,7 @@ static void OnFatalError(const char* location, const char* message) {
}
-void FatalException(TryCatch &try_catch) {
+void FatalException(TryCatch &try_catch, bool executionTerminated) {
HandleScope scope;
// Check if uncaught_exception_counter indicates a recursion
@@ -1762,7 +1765,12 @@ void FatalException(TryCatch &try_catch) {
Local<Function> emit = Local<Function>::Cast(emit_v);
- Local<Value> error = try_catch.Exception();
+ Local<Value> error;
+ if (executionTerminated) {
+ error = Exception::Error(String::New("Deadline Exceeded"));
+ } else {
+ error = try_catch.Exception();
+ }
Local<Value> event_argv[2] = { uncaught_exception_symbol_l, error };
uncaught_exception_counter++;
@@ -2748,6 +2756,28 @@ void StartThread(node::Isolate* isolate,
EmitExit(process_l);
}
+static uv_thread_t terminator_thread;
+static uv_loop_t* terminator_loop;
+static uv_timer_t terminator_watcher;
+
+static void TerminatorCallback(uv_timer_t* watcher, int status) {
+ assert(watcher == &terminator_watcher);
+ Isolate::TerminateExecutionIfDeadlineExceeded(uv_now(terminator_loop));
+}
+
+static void RunTerminator(void* arg) {
+ terminator_loop = uv_loop_new();
+
+ uv_timer_init(terminator_loop, &terminator_watcher);
+ uv_timer_start(&terminator_watcher, TerminatorCallback, 100, 100);
+
+ uv_run(terminator_loop);
+}
+
+static void StartTerminatorThread() {
+ uv_thread_create(&terminator_thread, RunTerminator, NULL);
+}
+
int Start(int argc, char *argv[]) {
// This needs to run *before* V8::Initialize()
@@ -2764,6 +2794,7 @@ int Start(int argc, char *argv[]) {
Isolate* isolate = new node::Isolate();
isolate->tid_ = tid;
isolate->Enter();
+ StartTerminatorThread();
StartThread(isolate, argc, argv);
isolate->Dispose();
View
3  src/node.h
@@ -117,7 +117,8 @@ do { \
enum encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX};
enum encoding ParseEncoding(v8::Handle<v8::Value> encoding_v,
enum encoding _default = BINARY);
-NODE_EXTERN void FatalException(v8::TryCatch &try_catch);
+NODE_EXTERN void FatalException(v8::TryCatch &try_catch,
+ bool executionTerminated = false);
void DisplayExceptionLine(v8::TryCatch &try_catch); // hack
v8::Local<v8::Value> Encode(const void *buf, size_t len,
View
10 src/node_atomic.h
@@ -21,6 +21,10 @@ class AtomicValue {
return (T) AO_load_read(&value_);
}
+ void Set(T value) {
+ AO_store_write(&value_, (AO_t) value);
+ }
+
T Swap(T value) {
AO_t old_value, new_value;
@@ -32,6 +36,12 @@ class AtomicValue {
return (T) old_value;
}
+ int Cas(T old_value, T new_value) {
+ return AO_compare_and_swap_full(&value_,
+ (AO_t) old_value,
+ (AO_t) new_value);
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(AtomicValue);
AO_t value_;
View
19 src/node_isolate.cc
@@ -73,6 +73,25 @@ void Isolate::JoinAll() {
uv_mutex_unlock(&list_lock);
}
+void Isolate::TerminateExecutionIfDeadlineExceeded(int64_t now) {
+ uv_mutex_lock(&list_lock);
+
+ ngx_queue_t* it;
+ ngx_queue_foreach(it, &list_head) {
+ Isolate* isolate = ngx_queue_data(it, Isolate, list_member_);
+ if (isolate->execution_status_.Get() == EXECUTING &&
+ now > isolate->deadline_) {
+ // Deadline exceeded, terminating
+ if (isolate->execution_status_.Cas(EXECUTING, TERMINATING)) {
+ v8::V8::TerminateExecution(isolate->v8_isolate_);
+ isolate->execution_status_.Set(IDLE);
+ }
+ }
+ }
+
+ uv_mutex_unlock(&list_lock);
+}
+
Isolate::Isolate() {
uv_mutex_lock(&list_lock);
View
21 src/node_isolate.h
@@ -25,6 +25,7 @@
#include "v8.h"
#include "uv.h"
#include "node_vars.h"
+#include "node_atomic.h"
#ifdef NDEBUG
# define NODE_ISOLATE_CHECK(ptr) ((void) (ptr))
@@ -59,6 +60,8 @@ class Isolate {
return reinterpret_cast<Isolate*>(v8::Isolate::GetCurrent()->GetData());
}
+ static void TerminateExecutionIfDeadlineExceeded(int64_t now);
+
uv_loop_t* GetLoop() {
NODE_ISOLATE_CHECK(this);
return loop_;
@@ -97,7 +100,21 @@ class Isolate {
/* Shutdown the isolate. Call this method at thread death. */
void Dispose();
+ void BeginExecution(int64_t deadline) {
+ deadline_ = deadline;
+ execution_status_.Set(EXECUTING);
+ }
+
+ bool EndExecution() {
+ if (execution_status_.Cas(EXECUTING, IDLE)) {
+ return false;
+ }
+ while (execution_status_.Get() != IDLE);
+ return true;
+ }
+
private:
+ DISALLOW_COPY_AND_ASSIGN(Isolate);
struct AtExitCallbackInfo {
ngx_queue_t at_exit_callbacks_;
@@ -110,6 +127,10 @@ class Isolate {
v8::Isolate* v8_isolate_;
uv_loop_t* loop_;
+ enum execution_status { IDLE, EXECUTING, TERMINATING };
+ AtomicValue<enum execution_status> execution_status_;
+ int64_t deadline_;
+
// Each isolate is a member of the static list_head.
ngx_queue_t list_member_;
Please sign in to comment.
Something went wrong with that request. Please try again.