From f28c6f7eef58e7c3133bb2cd457d05b986194ba3 Mon Sep 17 00:00:00 2001 From: Eugene Ostroukhov Date: Sat, 8 Sep 2018 19:45:10 -0700 Subject: inspector: workers debugging Introduce a NodeTarget inspector domain modelled after ChromeDevTools Target domain. It notifies inspector frontend attached to a main V8 isolate when workers are starting and allows passing messages to inspectors on their isolates. All inspector functionality is enabled on worker isolates. PR-URL: https://github.com/nodejs/node/pull/21364 Reviewed-By: Aleksei Koziatinskii Reviewed-By: Jan Krems Reviewed-By: Anna Henningsen --- src/inspector_agent.cc | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) (limited to 'src/inspector_agent.cc') diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index 63b9266353..ebb7b7d5bc 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -4,6 +4,8 @@ #include "inspector/main_thread_interface.h" #include "inspector/node_string.h" #include "inspector/tracing_agent.h" +#include "inspector/worker_agent.h" +#include "inspector/worker_inspector.h" #include "node/inspector/protocol/Protocol.h" #include "node_internals.h" #include "node_url.h" @@ -201,6 +203,7 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, public: explicit ChannelImpl(Environment* env, const std::unique_ptr& inspector, + std::shared_ptr worker_manager, std::unique_ptr delegate, bool prevent_shutdown) : delegate_(std::move(delegate)), @@ -209,11 +212,15 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, node_dispatcher_.reset(new protocol::UberDispatcher(this)); tracing_agent_.reset(new protocol::TracingAgent(env)); tracing_agent_->Wire(node_dispatcher_.get()); + worker_agent_.reset(new protocol::WorkerAgent(worker_manager)); + worker_agent_->Wire(node_dispatcher_.get()); } virtual ~ChannelImpl() { tracing_agent_->disable(); tracing_agent_.reset(); // Dispose before the dispatchers + worker_agent_->disable(); + worker_agent_.reset(); // Dispose before the dispatchers } std::string dispatchProtocolMessage(const StringView& message) { @@ -273,6 +280,7 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, } std::unique_ptr tracing_agent_; + std::unique_ptr worker_agent_; std::unique_ptr delegate_; std::unique_ptr session_; std::unique_ptr node_dispatcher_; @@ -469,7 +477,8 @@ class NodeInspectorClient : public V8InspectorClient { // TODO(addaleax): Revert back to using make_unique once we get issues // with CI resolved (i.e. revert the patch that added this comment). channels_[session_id].reset( - new ChannelImpl(env_, client_, std::move(delegate), prevent_shutdown)); + new ChannelImpl(env_, client_, getWorkerManager(), + std::move(delegate), prevent_shutdown)); return session_id; } @@ -589,6 +598,14 @@ class NodeInspectorClient : public V8InspectorClient { return interface_->GetHandle(); } + std::shared_ptr getWorkerManager() { + if (worker_manager_ == nullptr) { + worker_manager_ = + std::make_shared(getThreadHandle()); + } + return worker_manager_; + } + bool IsActive() { return !channels_.empty(); } @@ -646,6 +663,7 @@ class NodeInspectorClient : public V8InspectorClient { bool waiting_for_io_shutdown_ = false; // Allows accessing Inspector from non-main threads std::unique_ptr interface_; + std::shared_ptr worker_manager_; }; Agent::Agent(Environment* env) @@ -680,7 +698,10 @@ bool Agent::Start(const std::string& path, } bool wait_for_connect = options->wait_for_connect(); - if (!options->inspector_enabled || !StartIoThread()) { + if (parent_handle_) { + wait_for_connect = parent_handle_->WaitForConnect(); + parent_handle_->WorkerStarted(client_->getThreadHandle(), wait_for_connect); + } else if (!options->inspector_enabled || !StartIoThread()) { return false; } if (wait_for_connect) { @@ -727,7 +748,9 @@ std::unique_ptr Agent::Connect( void Agent::WaitForDisconnect() { CHECK_NOT_NULL(client_); - if (client_->hasConnectedSessions()) { + bool is_worker = parent_handle_ != nullptr; + parent_handle_.reset(); + if (client_->hasConnectedSessions() && !is_worker) { fprintf(stderr, "Waiting for the debugger to disconnect...\n"); fflush(stderr); } @@ -842,7 +865,11 @@ void Agent::ContextCreated(Local context, const ContextInfo& info) { } bool Agent::WillWaitForConnect() { - return debug_options_->wait_for_connect(); + if (debug_options_->wait_for_connect()) + return true; + if (parent_handle_) + return parent_handle_->WaitForConnect(); + return false; } bool Agent::IsActive() { @@ -851,11 +878,24 @@ bool Agent::IsActive() { return io_ != nullptr || client_->IsActive(); } +void Agent::AddWorkerInspector(int thread_id, + const std::string& url, + Agent* agent) { + CHECK_NOT_NULL(client_); + agent->parent_handle_ = + client_->getWorkerManager()->NewParentHandle(thread_id, url); +} + void Agent::WaitForConnect() { CHECK_NOT_NULL(client_); client_->waitForFrontend(); } +std::shared_ptr Agent::GetWorkerManager() { + CHECK_NOT_NULL(client_); + return client_->getWorkerManager(); +} + SameThreadInspectorSession::~SameThreadInspectorSession() { auto client = client_.lock(); if (client) -- cgit v1.2.3