inspector: Debugger.setAsyncCallStackDepth after waitingForDisconnect event crashes worker #28528
Closed
Description
- Version: v12.5.0
- Platform: Mac
- Subsystem: inspector
Create a snippet with following content to reproduce the crash:
const { Worker } = require('worker_threads');
const inspector = require('inspector');
(async function main() {
inspector.open(0, undefined, false);
const session = new inspector.Session;
await session.connect();
await session.post('NodeWorker.enable', { waitForDebuggerOnStart: true});
session.on('NodeWorker.attachedToWorker', async({params:{sessionId}}) => {
// enable debugger, otherwise setAsyncCallStackDepth does nothing
session.post('NodeWorker.sendMessageToWorker', {
sessionId,
message: JSON.stringify({id: 1, method: 'Debugger.enable'})
});
// enable waiting for disconnect notification
session.post('NodeWorker.sendMessageToWorker', {
sessionId,
message: JSON.stringify({id: 2, method: 'NodeRuntime.notifyWhenWaitingForDisconnect', params: {enabled: true}})
});
// start worker
session.post('NodeWorker.sendMessageToWorker', {
sessionId,
message: JSON.stringify({id: 3, method: 'Runtime.runIfWaitingForDebugger'})
});
// wait for notification
await new Promise(resolve => session.on('NodeWorker.receivedMessageFromWorker', ({params:{message}}) => {
if (JSON.parse(message).method === 'NodeRuntime.waitingForDisconnect')
resolve();
}));
// force call to node::inspector::Agent::ToggleAsyncHook by changing async call stack depth
await session.post('NodeWorker.sendMessageToWorker', {
sessionId,
message: JSON.stringify({id: 4, method: 'Debugger.setAsyncCallStackDepth', params: {maxDepth: 1}})
});
// BOOM!
await session.post('NodeWorker.detach', {
sessionId,
});
});
new Worker('console.log(42)', { eval: true });
})()
node crashes with following stack trace on node::inspector::Agent::ToggleAsyncHook call:
FATAL ERROR:
node::inspector::Agent::ToggleAsyncHook Cannot toggle Inspector's AsyncHook, please report this.
1: 0x10007643b node::Abort()
2: 0x100076b7c node::errors::TryCatchScope::~TryCatchScope()
3: 0x100076a0e node::OnFatalError(char const*, char const*)
4: 0x100106baf node::inspector::Agent::ToggleAsyncHook(v8::Isolate*, v8::Global<v8::Function> const&)
5: 0x10074cf63 v8_inspector::V8Debugger::setAsyncCallStackDepth(v8_inspector::V8DebuggerAgentImpl*, int)
6: 0x10075e964 v8_inspector::V8DebuggerAgentImpl::setAsyncCallStackDepth(int)
7: 0x100826369 v8_inspector::protocol::Debugger::DispatcherImpl::setAsyncCallStackDepth(int, v8_inspector::String16 const&, v8_inspector::protocol::ProtocolMessage const&, std::__1::unique_ptr<v8_inspector::protocol::DictionaryValue, std::__1::default_delete<v8_inspector::protocol::DictionaryValue> >, v8_inspector::protocol::ErrorSupport*)
8: 0x100822d64 v8_inspector::protocol::Debugger::DispatcherImpl::dispatch(int, v8_inspector::String16 const&, v8_inspector::protocol::ProtocolMessage const&, std::__1::unique_ptr<v8_inspector::protocol::DictionaryValue, std::__1::default_delete<v8_inspector::protocol::DictionaryValue> >)
9: 0x1008016a8 v8_inspector::protocol::UberDispatcher::dispatch(int, v8_inspector::String16 const&, std::__1::unique_ptr<v8_inspector::protocol::Value, std::__1::default_delete<v8_inspector::protocol::Value> >, v8_inspector::protocol::ProtocolMessage const&)
10: 0x10076da2a v8_inspector::V8InspectorSessionImpl::dispatchProtocolMessage(v8_inspector::StringView const&)
11: 0x100107cd5 node::inspector::NodeInspectorClient::dispatchMessageFromFrontend(int, v8_inspector::StringView const&)
12: 0x100107a1c node::inspector::(anonymous namespace)::SameThreadInspectorSession::Dispatch(v8_inspector::StringView const&)
13: 0x100114fda void node::inspector::(anonymous namespace)::AnotherThreadObjectReference<node::inspector::(anonymous namespace)::MainThreadSessionState>::Apply<std::__1::unique_ptr<v8_inspector::StringBuffer, std::__1::default_delete<v8_inspector::StringBuffer> > >(node::inspector::(anonymous namespace)::MainThreadSessionState*, void (node::inspector::(anonymous namespace)::MainThreadSessionState::*)(std::__1::unique_ptr<v8_inspector::StringBuffer, std::__1::default_delete<v8_inspector::StringBuffer> >), std::__1::unique_ptr<v8_inspector::StringBuffer, std::__1::default_delete<v8_inspector::StringBuffer> >&)
14: 0x1001140f1 node::inspector::MainThreadInterface::DispatchMessages()
15: 0x1000c8728 node::PerIsolatePlatformData::RunForegroundTask(std::__1::unique_ptr<v8::Task, std::__1::default_delete<v8::Task> >)
16: 0x1000c7b74 node::PerIsolatePlatformData::FlushForegroundTasksInternal()
17: 0x1000c8abb node::NodePlatform::FlushForegroundTasks(v8::Isolate*)
18: 0x1001071bd node::inspector::NodeInspectorClient::runMessageLoop()
19: 0x10010659f node::inspector::Agent::WaitForDisconnect()
20: 0x1000e054f std::__1::__function::__func<node::worker::Worker::Run()::$_0, std::__1::allocator<node::worker::Worker::Run()::$_0>, void ()>::operator()()
21: 0x1000a574f node::OnScopeLeave::~OnScopeLeave()
22: 0x1000ddd2f node::worker::Worker::Run()
23: 0x1000dfbbb node::worker::Worker::StartThread(v8::FunctionCallbackInfo<v8::Value> const&)::$_2::__invoke(void*)
24: 0x7fff692672eb _pthread_body [/usr/lib/system/libsystem_pthread.dylib]
25: 0x7fff6926a249 _pthread_start [/usr/lib/system/libsystem_pthread.dylib]
26: 0x7fff6926640d thread_start [/usr/lib/system/libsystem_pthread.dylib]
Abort trap: 6
I think that root of the issue is invalid state of node isolate when it is waiting for disconnect.
cc @eugeneo