diff --git a/src/node.cc b/src/node.cc index d75f0d039f4f6c..1bee586033515c 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3499,7 +3499,7 @@ void Init(int* argc, uv_disable_stdio_inheritance(); // init async debug messages dispatching - // FIXME(bnoordhuis) Should be per-isolate or per-context, not global. + // Main thread uses uv_default_loop uv_async_init(uv_default_loop(), &dispatch_debug_messages_async, DispatchDebugMessagesAsyncCallback); @@ -3663,6 +3663,18 @@ Environment* CreateEnvironment(Isolate* isolate, return env; } +static Environment* CreateEnvironment(Isolate* isolate, + Handle context, + NodeInstanceData* instance_data) { + return CreateEnvironment(isolate, + instance_data->event_loop(), + context, + instance_data->argc(), + instance_data->argv(), + instance_data->exec_argc(), + instance_data->exec_argv()); +} + static void HandleCloseCb(uv_handle_t* handle) { Environment* env = reinterpret_cast(handle->data); @@ -3746,62 +3758,32 @@ Environment* CreateEnvironment(Isolate* isolate, } -int Start(int argc, char** argv) { - PlatformInit(); - - const char* replaceInvalid = secure_getenv("NODE_INVALID_UTF8"); - - if (replaceInvalid == nullptr) - WRITE_UTF8_FLAGS |= String::REPLACE_INVALID_UTF8; - - CHECK_GT(argc, 0); - - // Hack around with the argv pointer. Used for process.title = "blah". - argv = uv_setup_args(argc, argv); - - // This needs to run *before* V8::Initialize(). The const_cast is not - // optional, in case you're wondering. - int exec_argc; - const char** exec_argv; - Init(&argc, const_cast(argv), &exec_argc, &exec_argv); - -#if HAVE_OPENSSL - // V8 on Windows doesn't have a good source of entropy. Seed it from - // OpenSSL's pool. - V8::SetEntropySource(crypto::EntropySource); -#endif - - V8::InitializePlatform(new Platform(4)); - - int code; - V8::Initialize(); - - // Fetch a reference to the main isolate, so we have a reference to it +// Entry point for new node instances, also called directly for the main +// node instance. +static void StartNodeInstance(void* arg) { + NodeInstanceData* instance_data = static_cast(arg); + Isolate* isolate = Isolate::New(); + // Fetch a reference to the main isolate, so we have a reference to it // even when we need it to access it from another (debugger) thread. - node_isolate = Isolate::New(); + if (instance_data->is_main()) + node_isolate = isolate; { - Locker locker(node_isolate); - Isolate::Scope isolate_scope(node_isolate); - HandleScope handle_scope(node_isolate); - Local context = Context::New(node_isolate); - Environment* env = CreateEnvironment( - node_isolate, - uv_default_loop(), - context, - argc, - argv, - exec_argc, - exec_argv); + Locker locker(isolate); + Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + Local context = Context::New(isolate); + Environment* env = CreateEnvironment(isolate, context, instance_data); Context::Scope context_scope(context); - env->set_using_abort_on_uncaught_exc(abort_on_uncaught_exception); + if (instance_data->is_main()) + env->set_using_abort_on_uncaught_exc(abort_on_uncaught_exception); // Start debug agent when argv has --debug - if (use_debug_agent) + if (instance_data->use_debug_agent()) StartDebug(env, debug_wait_connect); LoadEnvironment(env); // Enable debugger - if (use_debug_agent) + if (instance_data->use_debug_agent()) EnableDebug(env); bool more; @@ -3817,22 +3799,69 @@ int Start(int argc, char** argv) { more = true; } } while (more == true); - code = EmitExit(env); + + int exit_code = EmitExit(env); + if (instance_data->is_main()) + instance_data->set_exit_code(exit_code); RunAtExit(env); env->Dispose(); env = nullptr; } - CHECK_NE(node_isolate, nullptr); - node_isolate->Dispose(); - node_isolate = nullptr; + CHECK_NE(isolate, nullptr); + isolate->Dispose(); + isolate = nullptr; + if (instance_data->is_main()) + node_isolate = nullptr; +} + +int Start(int argc, char** argv) { + PlatformInit(); + + const char* replace_invalid = secure_getenv("NODE_INVALID_UTF8"); + + if (replace_invalid == nullptr) + WRITE_UTF8_FLAGS |= String::REPLACE_INVALID_UTF8; + + CHECK_GT(argc, 0); + + // Hack around with the argv pointer. Used for process.title = "blah". + argv = uv_setup_args(argc, argv); + + // This needs to run *before* V8::Initialize(). The const_cast is not + // optional, in case you're wondering. + int exec_argc; + const char** exec_argv; + Init(&argc, const_cast(argv), &exec_argc, &exec_argv); + +#if HAVE_OPENSSL + // V8 on Windows doesn't have a good source of entropy. Seed it from + // OpenSSL's pool. + V8::SetEntropySource(crypto::EntropySource); +#endif + + V8::InitializePlatform(new Platform(4)); + V8::Initialize(); + + int exit_code = 1; + { + NodeInstanceData instance_data(NodeInstanceType::MAIN, + uv_default_loop(), + argc, + const_cast(argv), + exec_argc, + exec_argv, + use_debug_agent); + StartNodeInstance(&instance_data); + exit_code = instance_data.exit_code(); + } V8::Dispose(); delete[] exec_argv; exec_argv = nullptr; - return code; + return exit_code; } diff --git a/src/node_internals.h b/src/node_internals.h index 92da0767befcb8..9141355df68aa9 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -210,6 +210,83 @@ inline void NODE_SET_EXTERNAL(v8::Handle target, v8::DontDelete)); } +enum NodeInstanceType { MAIN, WORKER }; + +class NodeInstanceData { + public: + NodeInstanceData(NodeInstanceType node_instance_type, + uv_loop_t* event_loop, + int argc, + const char** argv, + int exec_argc, + const char** exec_argv, + bool use_debug_agent_flag) + : node_instance_type_(node_instance_type), + exit_code_(1), + event_loop_(event_loop), + argc_(argc), + argv_(argv), + exec_argc_(exec_argc), + exec_argv_(exec_argv), + use_debug_agent_flag_(use_debug_agent_flag) { + CHECK_NE(event_loop_, nullptr); + } + + uv_loop_t* event_loop() const { + return event_loop_; + } + + int exit_code() { + CHECK(is_main()); + return exit_code_; + } + + void set_exit_code(int exit_code) { + CHECK(is_main()); + exit_code_ = exit_code; + } + + bool is_main() { + return node_instance_type_ == MAIN; + } + + bool is_worker() { + return node_instance_type_ == WORKER; + } + + int argc() { + return argc_; + } + + const char** argv() { + return argv_; + } + + int exec_argc() { + return exec_argc_; + } + + const char** exec_argv() { + return exec_argv_; + } + + bool use_debug_agent() { + return is_main() && use_debug_agent_flag_; + } + + private: + const NodeInstanceType node_instance_type_; + int exit_code_; + uv_loop_t* const event_loop_; + const int argc_; + const char** argv_; + const int exec_argc_; + const char** exec_argv_; + const bool use_debug_agent_flag_; + + DISALLOW_COPY_AND_ASSIGN(NodeInstanceData); +}; + } // namespace node #endif // SRC_NODE_INTERNALS_H_