aboutsummaryrefslogtreecommitdiff
path: root/src/node.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/node.cc')
-rw-r--r--src/node.cc202
1 files changed, 131 insertions, 71 deletions
diff --git a/src/node.cc b/src/node.cc
index 0e798b1353..1736f9fbb5 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -122,10 +122,6 @@ using v8::V8;
using v8::Value;
using v8::kExternalUint32Array;
-// FIXME(bnoordhuis) Make these per-context?
-QUEUE handle_wrap_queue = { &handle_wrap_queue, &handle_wrap_queue };
-QUEUE req_wrap_queue = { &req_wrap_queue, &req_wrap_queue };
-
static bool print_eval = false;
static bool force_repl = false;
static bool trace_deprecation = false;
@@ -1554,13 +1550,14 @@ static Local<Value> ExecuteString(Environment* env,
static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
- HandleScope scope(args.GetIsolate());
+ Environment* env = Environment::GetCurrent(args.GetIsolate());
+ HandleScope scope(env->isolate());
Local<Array> ary = Array::New(args.GetIsolate());
QUEUE* q = NULL;
int i = 0;
- QUEUE_FOREACH(q, &req_wrap_queue) {
+ QUEUE_FOREACH(q, env->req_wrap_queue()) {
ReqWrap<uv_req_t>* w = ContainerOf(&ReqWrap<uv_req_t>::req_wrap_queue_, q);
if (w->persistent().IsEmpty())
continue;
@@ -1583,7 +1580,7 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
Local<String> owner_sym = env->owner_string();
- QUEUE_FOREACH(q, &handle_wrap_queue) {
+ QUEUE_FOREACH(q, env->handle_wrap_queue()) {
HandleWrap* w = ContainerOf(&HandleWrap::handle_wrap_queue_, q);
if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref))
continue;
@@ -1967,8 +1964,8 @@ static void Uptime(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(env->isolate());
double uptime;
- uv_update_time(uv_default_loop());
- uptime = uv_now(uv_default_loop()) - prog_start_time;
+ uv_update_time(env->event_loop());
+ uptime = uv_now(env->event_loop()) - prog_start_time;
args.GetReturnValue().Set(Number::New(env->isolate(), uptime / 1000));
}
@@ -2860,9 +2857,12 @@ static void RawDebug(const FunctionCallbackInfo<Value>& args) {
}
-void Load(Environment* env) {
+void LoadEnvironment(Environment* env) {
HandleScope handle_scope(env->isolate());
+ V8::SetFatalErrorHandler(node::OnFatalError);
+ V8::AddMessageListener(OnMessage);
+
// Compile, execute the src/node.js file. (Which was included as static C
// string in node_natives.h. 'natve_node' is the string containing that
// source code.)
@@ -3121,40 +3121,33 @@ static void ParseArgs(int* argc,
// Called from V8 Debug Agent TCP thread.
-static void DispatchMessagesDebugAgentCallback() {
+static void DispatchMessagesDebugAgentCallback(Environment* env) {
+ // TODO(indutny): move async handle to environment
uv_async_send(&dispatch_debug_messages_async);
}
-// Called from the main thread.
-static void EnableDebug(Isolate* isolate, bool wait_connect) {
- assert(debugger_running == false);
- Isolate::Scope isolate_scope(isolate);
- HandleScope handle_scope(isolate);
- v8::Debug::SetDebugMessageDispatchHandler(DispatchMessagesDebugAgentCallback,
- false);
- debugger_running = v8::Debug::EnableAgent("node " NODE_VERSION,
- debug_port,
- wait_connect);
+static void StartDebug(Environment* env, bool wait) {
+ CHECK(!debugger_running);
+
+ env->debugger_agent()->set_dispatch_handler(
+ DispatchMessagesDebugAgentCallback);
+ debugger_running = env->debugger_agent()->Start(debug_port, wait);
if (debugger_running == false) {
fprintf(stderr, "Starting debugger on port %d failed\n", debug_port);
fflush(stderr);
return;
}
- fprintf(stderr, "Debugger listening on port %d\n", debug_port);
- fflush(stderr);
+}
- if (isolate == NULL)
- return; // Still starting up.
- Local<Context> context = isolate->GetCurrentContext();
- if (context.IsEmpty())
- return; // Still starting up.
- Environment* env = Environment::GetCurrent(context);
- // Assign environment to the debugger's context
- env->AssignToContext(v8::Debug::GetDebugContext());
+// Called from the main thread.
+static void EnableDebug(Environment* env) {
+ CHECK(debugger_running);
+
+ // Send message to enable debug in workers
+ HandleScope handle_scope(env->isolate());
- Context::Scope context_scope(env->context());
Local<Object> message = Object::New(env->isolate());
message->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "cmd"),
FIXED_ONE_BYTE_STRING(env->isolate(), "NODE_DEBUG_ENABLED"));
@@ -3163,6 +3156,9 @@ static void EnableDebug(Isolate* isolate, bool wait_connect) {
message
};
MakeCallback(env, env->process_object(), "emit", ARRAY_SIZE(argv), argv);
+
+ // Enabled debugger, possibly making it wait on a semaphore
+ env->debugger_agent()->Enable();
}
@@ -3170,7 +3166,12 @@ static void EnableDebug(Isolate* isolate, bool wait_connect) {
static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle) {
if (debugger_running == false) {
fprintf(stderr, "Starting debugger agent.\n");
- EnableDebug(node_isolate, false);
+
+ Environment* env = Environment::GetCurrent(node_isolate);
+ Context::Scope context_scope(env->context());
+
+ StartDebug(env, false);
+ EnableDebug(env);
}
Isolate::Scope isolate_scope(node_isolate);
v8::Debug::ProcessDebugMessages();
@@ -3399,7 +3400,8 @@ static void DebugPause(const FunctionCallbackInfo<Value>& args) {
static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
if (debugger_running) {
- v8::Debug::DisableAgent();
+ Environment* env = Environment::GetCurrent(args.GetIsolate());
+ env->debugger_agent()->Stop();
debugger_running = false;
}
}
@@ -3512,13 +3514,7 @@ void Init(int* argc,
RegisterSignalHandler(SIGTERM, SignalExit, true);
#endif // __POSIX__
- V8::SetFatalErrorHandler(node::OnFatalError);
- V8::AddMessageListener(OnMessage);
-
- // If the --debug flag was specified then initialize the debug thread.
- if (use_debug_agent) {
- EnableDebug(node_isolate, debug_wait_connect);
- } else {
+ if (!use_debug_agent) {
RegisterDebugSignalHandler();
}
}
@@ -3591,22 +3587,62 @@ int EmitExit(Environment* env) {
}
+// Just a convenience method
Environment* CreateEnvironment(Isolate* isolate,
Handle<Context> context,
int argc,
const char* const* argv,
int exec_argc,
const char* const* exec_argv) {
+ Environment* env;
+ Context::Scope context_scope(context);
+
+ env = CreateEnvironment(isolate,
+ uv_default_loop(),
+ context,
+ argc,
+ argv,
+ exec_argc,
+ exec_argv);
+
+ LoadEnvironment(env);
+
+ return env;
+}
+
+
+static void HandleCloseCb(uv_handle_t* handle) {
+ Environment* env = reinterpret_cast<Environment*>(handle->data);
+ env->FinishHandleCleanup(handle);
+}
+
+
+static void HandleCleanup(Environment* env,
+ uv_handle_t* handle,
+ void* arg) {
+ handle->data = env;
+ uv_close(handle, HandleCloseCb);
+}
+
+
+Environment* CreateEnvironment(Isolate* isolate,
+ uv_loop_t* loop,
+ Handle<Context> context,
+ int argc,
+ const char* const* argv,
+ int exec_argc,
+ const char* const* exec_argv) {
HandleScope handle_scope(isolate);
Context::Scope context_scope(context);
- Environment* env = Environment::New(context);
+ Environment* env = Environment::New(context, loop);
isolate->SetAutorunMicrotasks(false);
uv_check_init(env->event_loop(), env->immediate_check_handle());
uv_unref(
reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
+
uv_idle_init(env->event_loop(), env->immediate_idle_handle());
// Inform V8's CPU profiler when we're idle. The profiler is sampling-based
@@ -3623,6 +3659,24 @@ Environment* CreateEnvironment(Isolate* isolate,
uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));
uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle()));
+ // Register handle cleanups
+ env->RegisterHandleCleanup(
+ reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()),
+ HandleCleanup,
+ NULL);
+ env->RegisterHandleCleanup(
+ reinterpret_cast<uv_handle_t*>(env->immediate_idle_handle()),
+ HandleCleanup,
+ NULL);
+ env->RegisterHandleCleanup(
+ reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()),
+ HandleCleanup,
+ NULL);
+ env->RegisterHandleCleanup(
+ reinterpret_cast<uv_handle_t*>(env->idle_check_handle()),
+ HandleCleanup,
+ NULL);
+
if (v8_is_profiling) {
StartProfilerIdleNotifier(env);
}
@@ -3634,7 +3688,6 @@ Environment* CreateEnvironment(Isolate* isolate,
env->set_process_object(process_object);
SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
- Load(env);
return env;
}
@@ -3676,34 +3729,41 @@ int Start(int argc, char** argv) {
HandleScope handle_scope(node_isolate);
Local<Context> context = Context::New(node_isolate);
Environment* env = CreateEnvironment(
- node_isolate, context, argc, argv, exec_argc, exec_argv);
- // Assign env to the debugger's context
- if (debugger_running) {
- HandleScope scope(env->isolate());
- env->AssignToContext(v8::Debug::GetDebugContext());
- }
- // This Context::Scope is here so EnableDebug() can look up the current
- // environment with Environment::GetCurrent().
- // TODO(bnoordhuis) Reorder the debugger initialization logic so it can
- // be removed.
- {
- Context::Scope context_scope(env->context());
- bool more;
- do {
- more = uv_run(env->event_loop(), UV_RUN_ONCE);
- if (more == false) {
- EmitBeforeExit(env);
-
- // Emit `beforeExit` if the loop became alive either after emitting
- // event, or after running some callbacks.
- more = uv_loop_alive(env->event_loop());
- if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
- more = true;
- }
- } while (more == true);
- code = EmitExit(env);
- RunAtExit(env);
- }
+ node_isolate,
+ uv_default_loop(),
+ context,
+ argc,
+ argv,
+ exec_argc,
+ exec_argv);
+ Context::Scope context_scope(context);
+
+ // Start debug agent when argv has --debug
+ if (use_debug_agent)
+ StartDebug(env, debug_wait_connect);
+
+ LoadEnvironment(env);
+
+ // Enable debugger
+ if (use_debug_agent)
+ EnableDebug(env);
+
+ bool more;
+ do {
+ more = uv_run(env->event_loop(), UV_RUN_ONCE);
+ if (more == false) {
+ EmitBeforeExit(env);
+
+ // Emit `beforeExit` if the loop became alive either after emitting
+ // event, or after running some callbacks.
+ more = uv_loop_alive(env->event_loop());
+ if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
+ more = true;
+ }
+ } while (more == true);
+ code = EmitExit(env);
+ RunAtExit(env);
+
env->Dispose();
env = NULL;
}