Skip to content

Commit 23119ca

Browse files
alexkozytargos
authored andcommitted
inspector: supported NodeRuntime domain in worker
NodeRuntime domain was introduced to give inspector client way to fetch captured information before Node process is gone. We need similar capability for work. With current protocol inspector client can force worker to wait on start by passing waitForDebuggerOnStart flag to NodeWorker.enable method. So client has some time to setup environment, e.g. start profiler. At the same time there is no way to prevent worker from being terminated. So we can start capturing profile but we can not reliably get captured data back. This PR implemented NodeRuntime.notifyWhenWaitingForDisconnect method for worker. When NodeRuntime.waitingForDisconnect notification is enabled, worker will wait for explicit NodeWorker.detach call. With this PR worker tooling story is nicely aligned with main thread tooling story. The only difference is that main thread by default is waiting for disconnect but worker thread is not waiting. Issue: #27677 PR-URL: #27706 Reviewed-By: Eugene Ostroukhov <eostroukhov@google.com>
1 parent 6a5ce36 commit 23119ca

6 files changed

Lines changed: 70 additions & 10 deletions

File tree

‎src/inspector/node_protocol.pdl‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ experimental domain NodeWorker
7171
# Detaches from all running workers and disables attaching to new workers as they are started.
7272
command disable
7373

74+
# Detached from the worker with given sessionId.
75+
command detach
76+
parameters
77+
SessionID sessionId
78+
7479
# Issued when attached to a worker.
7580
event attachedToWorker
7681
parameters

‎src/inspector/runtime_agent.cc‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ void RuntimeAgent::Wire(UberDispatcher* dispatcher) {
1616
}
1717

1818
DispatchResponse RuntimeAgent::notifyWhenWaitingForDisconnect(bool enabled) {
19-
if (!env_->owns_process_state()) {
20-
returnDispatchResponse::Error(
21-
"NodeRuntime domain can only be used through main thread sessions");
22-
}
2319
notify_when_waiting_for_disconnect_ = enabled;
2420
returnDispatchResponse::OK();
2521
}

‎src/inspector/worker_agent.cc‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ DispatchResponse WorkerAgent::disable() {
115115
returnDispatchResponse::OK();
116116
}
117117

118+
DispatchResponse WorkerAgent::detach(const String& sessionId) {
119+
workers_->Detached(sessionId);
120+
returnDispatchResponse::OK();
121+
}
122+
118123
voidNodeWorkers::WorkerCreated(const std::string& title,
119124
const std::string& url,
120125
bool waiting,

‎src/inspector/worker_agent.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class WorkerAgent : public NodeWorker::Backend {
2525

2626
DispatchResponse enable(bool waitForDebuggerOnStart) override;
2727
DispatchResponse disable() override;
28+
DispatchResponse detach(const String& sessionId) override;
2829

2930
private:
3031
std::shared_ptr<NodeWorker::Frontend> frontend_;

‎src/inspector_agent.cc‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -472,8 +472,8 @@ class NodeInspectorClient : public V8InspectorClient {
472472
runMessageLoop();
473473
}
474474

475-
voidwaitForIoShutdown() {
476-
waiting_for_io_shutdown_ = true;
475+
voidwaitForSessionsDisconnect() {
476+
waiting_for_sessions_disconnect_ = true;
477477
runMessageLoop();
478478
}
479479

@@ -548,6 +548,8 @@ class NodeInspectorClient : public V8InspectorClient {
548548
}
549549
contextDestroyed(env_->context());
550550
}
551+
if (waiting_for_sessions_disconnect_ && !is_main_)
552+
waiting_for_sessions_disconnect_ = false;
551553
}
552554

553555
voiddispatchMessageFromFrontend(int session_id, const StringView& message) {
@@ -678,8 +680,9 @@ class NodeInspectorClient : public V8InspectorClient {
678680
boolshouldRunMessageLoop() {
679681
if (waiting_for_frontend_)
680682
returntrue;
681-
if (waiting_for_io_shutdown_ || waiting_for_resume_)
683+
if (waiting_for_sessions_disconnect_ || waiting_for_resume_) {
682684
returnhasConnectedSessions();
685+
}
683686
returnfalse;
684687
}
685688

@@ -723,7 +726,7 @@ class NodeInspectorClient : public V8InspectorClient {
723726
int next_session_id_ = 1;
724727
bool waiting_for_resume_ = false;
725728
bool waiting_for_frontend_ = false;
726-
boolwaiting_for_io_shutdown_ = false;
729+
boolwaiting_for_sessions_disconnect_ = false;
727730
// Allows accessing Inspector from non-main threads
728731
std::unique_ptr<MainThreadInterface> interface_;
729732
std::shared_ptr<WorkerManager> worker_manager_;
@@ -819,11 +822,14 @@ void Agent::WaitForDisconnect() {
819822
fprintf(stderr, "Waiting for the debugger to disconnect...\n");
820823
fflush(stderr);
821824
}
822-
if (!client_->notifyWaitingForDisconnect())
825+
if (!client_->notifyWaitingForDisconnect()) {
823826
client_->contextDestroyed(parent_env_->context());
827+
} elseif (is_worker) {
828+
client_->waitForSessionsDisconnect();
829+
}
824830
if (io_ != nullptr) {
825831
io_->StopAcceptingNewConnections();
826-
client_->waitForIoShutdown();
832+
client_->waitForSessionsDisconnect();
827833
}
828834
}
829835

‎test/parallel/test-worker-debug.js‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,52 @@ async function testTwoWorkers(session, post) {
206206
awaitPromise.all([worker1Exited,worker2Exited]);
207207
}
208208

209+
asyncfunctiontestWaitForDisconnectInWorker(session,post){
210+
console.log('Test NodeRuntime.waitForDisconnect in worker');
211+
212+
constsessionWithoutWaiting=newSession();
213+
sessionWithoutWaiting.connect();
214+
constsessionWithoutWaitingPost=doPost.bind(null,sessionWithoutWaiting);
215+
216+
awaitsessionWithoutWaitingPost('NodeWorker.enable',{
217+
waitForDebuggerOnStart: true
218+
});
219+
awaitpost('NodeWorker.enable',{waitForDebuggerOnStart: true});
220+
221+
constattached=[
222+
waitForWorkerAttach(session),
223+
waitForWorkerAttach(sessionWithoutWaiting)
224+
];
225+
226+
letworker=null;
227+
constexitPromise=runWorker(2,(w)=>worker=w);
228+
229+
const[{sessionId: sessionId1},{sessionId: sessionId2}]=
230+
awaitPromise.all(attached);
231+
232+
constworkerSession1=newWorkerSession(session,sessionId1);
233+
constworkerSession2=newWorkerSession(sessionWithoutWaiting,sessionId2);
234+
235+
awaitworkerSession2.post('Runtime.enable');
236+
awaitworkerSession1.post('Runtime.enable');
237+
awaitworkerSession1.post('NodeRuntime.notifyWhenWaitingForDisconnect',{
238+
enabled: true
239+
});
240+
awaitworkerSession1.post('Runtime.runIfWaitingForDebugger');
241+
242+
worker.postMessage('resume');
243+
244+
awaitwaitForEvent(workerSession1,'NodeRuntime.waitingForDisconnect');
245+
post('NodeWorker.detach',{sessionId: sessionId1});
246+
awaitwaitForEvent(workerSession2,'Runtime.executionContextDestroyed');
247+
248+
awaitexitPromise;
249+
250+
awaitpost('NodeWorker.disable');
251+
awaitsessionWithoutWaitingPost('NodeWorker.disable');
252+
sessionWithoutWaiting.disconnect();
253+
}
254+
209255
asyncfunctiontest(){
210256
constsession=newSession();
211257
session.connect();
@@ -219,6 +265,7 @@ async function test() {
219265

220266
awaittestNoWaitOnStart(session,post);
221267
awaittestTwoWorkers(session,post);
268+
awaittestWaitForDisconnectInWorker(session,post);
222269

223270
session.disconnect();
224271
console.log('Test done');

0 commit comments

Comments
 (0)