diff --git a/src/env.cc b/src/env.cc index 85239c02a91141..f541188e73b24f 100644 --- a/src/env.cc +++ b/src/env.cc @@ -349,8 +349,6 @@ Environment::Environment(IsolateData* isolate_data, credentials::SafeGetenv("NODE_DEBUG_NATIVE", &debug_cats, this); set_debug_categories(debug_cats, true); - isolate()->GetHeapProfiler()->AddBuildEmbedderGraphCallback( - BuildEmbedderGraph, this); if (options_->no_force_async_hooks_checks) { async_hooks_.no_force_checks(); } diff --git a/src/env.h b/src/env.h index 778f0aa1e2f54f..f3d6ec4d474805 100644 --- a/src/env.h +++ b/src/env.h @@ -75,6 +75,10 @@ class V8CoverageConnection; class V8CpuProfilerConnection; class V8HeapProfilerConnection; } // namespace profiler + +namespace inspector { +class ParentInspectorHandle; +} #endif // HAVE_INSPECTOR namespace worker { @@ -797,6 +801,13 @@ class Environment : public MemoryRetainer { void MemoryInfo(MemoryTracker* tracker) const override; void CreateProperties(); + // Should be called before InitializeInspector() + void InitializeDiagnostics(); +#if HAVE_INSPECTOR && NODE_USE_V8_PLATFORM + // If the environment is created for a worker, pass parent_handle and + // the ownership if transferred into the Environment. + int InitializeInspector(inspector::ParentInspectorHandle* parent_handle); +#endif inline size_t async_callback_scope_depth() const; inline void PushAsyncCallbackScope(); diff --git a/src/inspector/worker_inspector.h b/src/inspector/worker_inspector.h index 9f5604e79aba2d..cf483ae49ebbe1 100644 --- a/src/inspector/worker_inspector.h +++ b/src/inspector/worker_inspector.h @@ -60,6 +60,7 @@ class ParentInspectorHandle { bool WaitForConnect() { return wait_; } + const std::string& url() const { return url_; } private: int id_; diff --git a/src/node.cc b/src/node.cc index 3b4ddd6647a6c4..095ee53693dbbc 100644 --- a/src/node.cc +++ b/src/node.cc @@ -47,6 +47,7 @@ #endif #if HAVE_INSPECTOR +#include "inspector_agent.h" #include "inspector_io.h" #endif @@ -59,6 +60,10 @@ #endif // NODE_USE_V8_PLATFORM #include "v8-profiler.h" +#if HAVE_INSPECTOR +#include "inspector/worker_inspector.h" // ParentInspectorHandle +#endif + #ifdef NODE_ENABLE_VTUNE_PROFILING #include "../deps/v8/src/third_party/vtune/v8-vtune.h" #endif @@ -125,7 +130,6 @@ using v8::Local; using v8::Maybe; using v8::MaybeLocal; using v8::Object; -using v8::Script; using v8::String; using v8::Undefined; using v8::V8; @@ -222,6 +226,51 @@ MaybeLocal ExecuteBootstrapper(Environment* env, return scope.EscapeMaybe(result); } +#if HAVE_INSPECTOR && NODE_USE_V8_PLATFORM +int Environment::InitializeInspector( + inspector::ParentInspectorHandle* parent_handle) { + std::string inspector_path; + if (parent_handle != nullptr) { + DCHECK(!is_main_thread()); + inspector_path = parent_handle->url(); + inspector_agent_->SetParentHandle( + std::unique_ptr(parent_handle)); + } else { + inspector_path = argv_.size() > 1 ? argv_[1].c_str() : ""; + } + + CHECK(!inspector_agent_->IsListening()); + // Inspector agent can't fail to start, but if it was configured to listen + // right away on the websocket port and fails to bind/etc, this will return + // false. + inspector_agent_->Start(inspector_path, + options_->debug_options(), + inspector_host_port(), + is_main_thread()); + if (options_->debug_options().inspector_enabled && + !inspector_agent_->IsListening()) { + return 12; // Signal internal error + } + + profiler::StartProfilers(this); + + if (options_->debug_options().break_node_first_line) { + inspector_agent_->PauseOnNextJavascriptStatement("Break at bootstrap"); + } + + return 0; +} +#endif // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM + +void Environment::InitializeDiagnostics() { + isolate_->GetHeapProfiler()->AddBuildEmbedderGraphCallback( + Environment::BuildEmbedderGraph, this); + +#if defined HAVE_DTRACE || defined HAVE_ETW + InitDTrace(this); +#endif +} + MaybeLocal RunBootstrapping(Environment* env) { CHECK(!env->has_run_bootstrapping_code()); @@ -229,17 +278,9 @@ MaybeLocal RunBootstrapping(Environment* env) { Isolate* isolate = env->isolate(); Local context = env->context(); -#if HAVE_INSPECTOR - profiler::StartProfilers(env); -#endif // HAVE_INSPECTOR // Add a reference to the global object Local global = context->Global(); - -#if defined HAVE_DTRACE || defined HAVE_ETW - InitDTrace(env); -#endif - Local process = env->process_object(); // Setting global properties for the bootstrappers to use: @@ -249,12 +290,6 @@ MaybeLocal RunBootstrapping(Environment* env) { global->Set(context, FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global) .Check(); -#if HAVE_INSPECTOR - if (env->options()->debug_options().break_node_first_line) { - env->inspector_agent()->PauseOnNextJavascriptStatement( - "Break at bootstrap"); - } -#endif // HAVE_INSPECTOR // Create binding loaders std::vector> loaders_params = { diff --git a/src/node_main_instance.cc b/src/node_main_instance.cc index c9b0a24099d909..d724f392cda64c 100644 --- a/src/node_main_instance.cc +++ b/src/node_main_instance.cc @@ -194,27 +194,16 @@ std::unique_ptr NodeMainInstance::CreateMainEnvironment( Environment::kOwnsProcessState | Environment::kOwnsInspector)); env->InitializeLibuv(per_process::v8_is_profiling); + env->InitializeDiagnostics(); + // TODO(joyeecheung): when we snapshot the bootstrapped context, + // the inspector and diagnostics setup should after after deserialization. #if HAVE_INSPECTOR && NODE_USE_V8_PLATFORM - CHECK(!env->inspector_agent()->IsListening()); - // Inspector agent can't fail to start, but if it was configured to listen - // right away on the websocket port and fails to bind/etc, this will return - // false. - env->inspector_agent()->Start(args_.size() > 1 ? args_[1].c_str() : "", - env->options()->debug_options(), - env->inspector_host_port(), - true); - if (env->options()->debug_options().inspector_enabled && - !env->inspector_agent()->IsListening()) { - *exit_code = 12; // Signal internal error. + *exit_code = env->InitializeInspector(nullptr); +#endif + if (*exit_code != 0) { return env; } -#else - // inspector_enabled can't be true if !HAVE_INSPECTOR or - // !NODE_USE_V8_PLATFORM - // - the option parser should not allow that. - CHECK(!env->options()->debug_options().inspector_enabled); -#endif // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM if (RunBootstrapping(env.get()).IsEmpty()) { *exit_code = 1; diff --git a/src/node_worker.cc b/src/node_worker.cc index b4fd0028af39f8..239e71c56f7967 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -42,17 +42,6 @@ namespace worker { namespace { #if NODE_USE_V8_PLATFORM && HAVE_INSPECTOR -void StartWorkerInspector( - Environment* child, - std::unique_ptr parent_handle, - const std::string& url) { - child->inspector_agent()->SetParentHandle(std::move(parent_handle)); - child->inspector_agent()->Start(url, - child->options()->debug_options(), - child->inspector_host_port(), - false); -} - void WaitForWorkerInspectorToStop(Environment* child) { child->inspector_agent()->WaitForDisconnect(); child->inspector_agent()->Stop(); @@ -67,11 +56,10 @@ Worker::Worker(Environment* env, std::shared_ptr per_isolate_opts, std::vector&& exec_argv) : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_WORKER), - url_(url), per_isolate_opts_(per_isolate_opts), exec_argv_(exec_argv), platform_(env->isolate_data()->platform()), - profiler_idle_notifier_started_(env->profiler_idle_notifier_started()), + start_profiler_idle_notifier_(env->profiler_idle_notifier_started()), thread_id_(Environment::AllocateThreadId()), env_vars_(env->env_vars()) { Debug(this, "Creating new worker instance with thread id %llu", thread_id_); @@ -265,7 +253,7 @@ void Worker::Run() { env_->set_abort_on_uncaught_exception(false); env_->set_worker_context(this); - env_->InitializeLibuv(profiler_idle_notifier_started_); + env_->InitializeLibuv(start_profiler_idle_notifier_); } { Mutex::ScopedLock lock(mutex_); @@ -275,13 +263,11 @@ void Worker::Run() { Debug(this, "Created Environment for worker with id %llu", thread_id_); if (is_stopped()) return; { + env_->InitializeDiagnostics(); #if NODE_USE_V8_PLATFORM && HAVE_INSPECTOR - StartWorkerInspector(env_.get(), - std::move(inspector_parent_handle_), - url_); -#endif + env_->InitializeInspector(inspector_parent_handle_.release()); inspector_started = true; - +#endif HandleScope handle_scope(isolate_); AsyncCallbackScope callback_scope(env_.get()); env_->async_hooks()->push_async_ids(1, 0); diff --git a/src/node_worker.h b/src/node_worker.h index 8239826a0e8b04..0e659a9f522cda 100644 --- a/src/node_worker.h +++ b/src/node_worker.h @@ -54,7 +54,6 @@ class Worker : public AsyncWrap { private: void OnThreadStopped(); void CreateEnvMessagePort(Environment* env); - const std::string url_; std::shared_ptr per_isolate_opts_; std::vector exec_argv_; @@ -62,7 +61,7 @@ class Worker : public AsyncWrap { MultiIsolatePlatform* platform_; v8::Isolate* isolate_ = nullptr; - bool profiler_idle_notifier_started_; + bool start_profiler_idle_notifier_; uv_thread_t tid_; #if NODE_USE_V8_PLATFORM && HAVE_INSPECTOR