diff options
Diffstat (limited to 'src/node.cc')
-rw-r--r-- | src/node.cc | 202 |
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; } |