src: reorganize inspector and diagnostics initialization

- Split the initialization of the inspector and other diagnostics
  into `Environment::InitializeInspector()` and
  `Environment::InitializeDiagnostics()` - these need to be
  reinitialized separately after snapshot deserialization.
- Do not store worker url alongside the inspector parent handle,
  instead just get it from the handle.
- Rename `Worker::profiler_idle_notifier_started_` to
  `Worker::start_profiler_idle_notifier_` because it stores
  the state inherited from the parent env to use for initializing
  itself.

PR-URL: https://github.com/nodejs/node/pull/27539
Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
Joyee Cheung 2019-05-20 13:39:21 +02:00
parent a1a690e07c
commit a0d86befb5
No known key found for this signature in database
GPG Key ID: 92B78A53C8303B8D
7 changed files with 74 additions and 55 deletions

View File

@ -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();
}

View File

@ -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();

View File

@ -60,6 +60,7 @@ class ParentInspectorHandle {
bool WaitForConnect() {
return wait_;
}
const std::string& url() const { return url_; }
private:
int id_;

View File

@ -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
@ -136,7 +141,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;
@ -228,6 +232,51 @@ MaybeLocal<Value> 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<inspector::ParentInspectorHandle>(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<Value> RunBootstrapping(Environment* env) {
CHECK(!env->has_run_bootstrapping_code());
@ -235,17 +284,9 @@ MaybeLocal<Value> RunBootstrapping(Environment* env) {
Isolate* isolate = env->isolate();
Local<Context> context = env->context();
#if HAVE_INSPECTOR
profiler::StartProfilers(env);
#endif // HAVE_INSPECTOR
// Add a reference to the global object
Local<Object> global = context->Global();
#if defined HAVE_DTRACE || defined HAVE_ETW
InitDTrace(env);
#endif
Local<Object> process = env->process_object();
// Setting global properties for the bootstrappers to use:
@ -255,12 +296,6 @@ MaybeLocal<Value> 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<Local<String>> loaders_params = {

View File

@ -194,27 +194,16 @@ std::unique_ptr<Environment> 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;

View File

@ -42,17 +42,6 @@ namespace worker {
namespace {
#if NODE_USE_V8_PLATFORM && HAVE_INSPECTOR
void StartWorkerInspector(
Environment* child,
std::unique_ptr<inspector::ParentInspectorHandle> 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<PerIsolateOptions> per_isolate_opts,
std::vector<std::string>&& 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);

View File

@ -54,7 +54,6 @@ class Worker : public AsyncWrap {
private:
void OnThreadStopped();
void CreateEnvMessagePort(Environment* env);
const std::string url_;
std::shared_ptr<PerIsolateOptions> per_isolate_opts_;
std::vector<std::string> 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