From d72b6820bd05f076e80e1beaf699a85172c88491 Mon Sep 17 00:00:00 2001 From: Eugene Ostroukhov Date: Fri, 26 Jul 2019 16:38:15 -0700 Subject: [PATCH] inspector: report all workers Main thread (the one that WS endpoint connects to) should be able to report all workers. PR-URL: https://github.com/nodejs/node/pull/28872 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Rich Trott --- src/inspector/worker_inspector.h | 7 ++ src/inspector_agent.cc | 21 +++-- .../test-inspector-async-hook-after-done.js | 11 ++- .../test-inspector-workers-flat-list.js | 78 +++++++++++++++++++ 4 files changed, 108 insertions(+), 9 deletions(-) create mode 100644 test/parallel/test-inspector-workers-flat-list.js diff --git a/src/inspector/worker_inspector.h b/src/inspector/worker_inspector.h index cf483ae49ebbe1..c0961496cec1bd 100644 --- a/src/inspector/worker_inspector.h +++ b/src/inspector/worker_inspector.h @@ -55,6 +55,13 @@ class ParentInspectorHandle { std::shared_ptr parent_thread, bool wait_for_connect); ~ParentInspectorHandle(); + std::unique_ptr NewParentInspectorHandle( + int thread_id, const std::string& url) { + return std::make_unique(thread_id, + url, + parent_thread_, + wait_); + } void WorkerStarted(std::shared_ptr worker_thread, bool waiting); bool WaitForConnect() { diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index e392be8595f4eb..2965483dea6244 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -237,8 +237,10 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, tracing_agent_ = std::make_unique(env, main_thread_); tracing_agent_->Wire(node_dispatcher_.get()); - worker_agent_ = std::make_unique(worker_manager); - worker_agent_->Wire(node_dispatcher_.get()); + if (worker_manager) { + worker_agent_ = std::make_unique(worker_manager); + worker_agent_->Wire(node_dispatcher_.get()); + } runtime_agent_ = std::make_unique(); runtime_agent_->Wire(node_dispatcher_.get()); } @@ -246,8 +248,10 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, ~ChannelImpl() override { tracing_agent_->disable(); tracing_agent_.reset(); // Dispose before the dispatchers - worker_agent_->disable(); - worker_agent_.reset(); // Dispose before the dispatchers + if (worker_agent_) { + worker_agent_->disable(); + worker_agent_.reset(); // Dispose before the dispatchers + } runtime_agent_->disable(); runtime_agent_.reset(); // Dispose before the dispatchers } @@ -670,6 +674,9 @@ class NodeInspectorClient : public V8InspectorClient { } std::shared_ptr getWorkerManager() { + if (!is_main_) { + return nullptr; + } if (worker_manager_ == nullptr) { worker_manager_ = std::make_shared(getThreadHandle()); @@ -968,7 +975,11 @@ void Agent::SetParentHandle( std::unique_ptr Agent::GetParentHandle( int thread_id, const std::string& url) { - return client_->getWorkerManager()->NewParentHandle(thread_id, url); + if (!parent_handle_) { + return client_->getWorkerManager()->NewParentHandle(thread_id, url); + } else { + return parent_handle_->NewParentInspectorHandle(thread_id, url); + } } void Agent::WaitForConnect() { diff --git a/test/parallel/test-inspector-async-hook-after-done.js b/test/parallel/test-inspector-async-hook-after-done.js index 10916acd0f8647..9f96fdb7b0da84 100644 --- a/test/parallel/test-inspector-async-hook-after-done.js +++ b/test/parallel/test-inspector-async-hook-after-done.js @@ -3,6 +3,7 @@ const common = require('../common'); common.skipIfInspectorDisabled(); +common.skipIfWorker(); const assert = require('assert'); const { Worker } = require('worker_threads'); @@ -12,9 +13,7 @@ const session = new Session(); let done = false; -session.connect(); - -session.on('NodeWorker.attachedToWorker', ({ params: { sessionId } }) => { +function onAttachToWorker({ params: { sessionId } }) { let id = 1; function postToWorkerInspector(method, params) { session.post('NodeWorker.sendMessageToWorker', { @@ -47,7 +46,11 @@ session.on('NodeWorker.attachedToWorker', ({ params: { sessionId } }) => { { enabled: true }); // start worker postToWorkerInspector('Runtime.runIfWaitingForDebugger'); -}); +} + +session.connect(); + +session.on('NodeWorker.attachedToWorker', common.mustCall(onAttachToWorker)); session.post('NodeWorker.enable', { waitForDebuggerOnStart: true }, () => { new Worker('console.log("Worker is done")', { eval: true }) diff --git a/test/parallel/test-inspector-workers-flat-list.js b/test/parallel/test-inspector-workers-flat-list.js new file mode 100644 index 00000000000000..9f6495d10fb147 --- /dev/null +++ b/test/parallel/test-inspector-workers-flat-list.js @@ -0,0 +1,78 @@ +'use strict'; +const common = require('../common'); + +common.skipIfInspectorDisabled(); + +const { Worker, isMainThread, parentPort, workerData } = + require('worker_threads'); + +if (isMainThread || workerData !== 'launched by test') { + common.skipIfWorker(); +} + +const { Session } = require('inspector'); + +const MAX_DEPTH = 3; + +let rootWorker = null; + +const runTest = common.mustCall(function() { + let reportedWorkersCount = 0; + const session = new Session(); + session.connect(); + session.on('NodeWorker.attachedToWorker', common.mustCall( + ({ params: { workerInfo } }) => { + console.log(`Worker ${workerInfo.title} was reported`); + if (++reportedWorkersCount === MAX_DEPTH) { + rootWorker.postMessage({ done: true }); + } + }, MAX_DEPTH)); + session.post('NodeWorker.enable', { waitForDebuggerOnStart: false }); +}); + +function processMessage({ child }) { + console.log(`Worker ${child} is running`); + if (child === MAX_DEPTH) { + runTest(); + } +} + +function workerCallback(message) { + parentPort.postMessage(message); +} + +function startWorker(depth, messageCallback) { + const worker = new Worker(__filename, { workerData: 'launched by test' }); + worker.on('message', messageCallback); + worker.postMessage({ depth }); + return worker; +} + +function runMainThread() { + rootWorker = startWorker(1, processMessage); +} + +function runChildWorkerThread() { + let worker = null; + parentPort.on('message', ({ child, depth, done }) => { + if (done) { + if (worker) { + worker.postMessage({ done: true }); + } + parentPort.close(); + } else if (depth) { + parentPort.postMessage({ child: depth }); + if (depth < MAX_DEPTH) { + worker = startWorker(depth + 1, workerCallback); + } + } else if (child) { + parentPort.postMessage({ child }); + } + }); +} + +if (isMainThread) { + runMainThread(); +} else { + runChildWorkerThread(); +}