diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index 216b43ca6c3379..95e1d642915b5c 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -325,10 +325,12 @@ class NodeInspectorClient : public V8InspectorClient { } void maxAsyncCallStackDepthChanged(int depth) override { - if (depth == 0) { - env_->inspector_agent()->DisableAsyncHook(); - } else { - env_->inspector_agent()->EnableAsyncHook(); + if (auto agent = env_->inspector_agent()) { + if (depth == 0) { + agent->DisableAsyncHook(); + } else { + agent->EnableAsyncHook(); + } } } diff --git a/test/sequential/test-inspector-async-call-stack-abort.js b/test/sequential/test-inspector-async-call-stack-abort.js new file mode 100644 index 00000000000000..1ec46ab3cfeb9d --- /dev/null +++ b/test/sequential/test-inspector-async-call-stack-abort.js @@ -0,0 +1,34 @@ +// Check that abrupt termination when async call stack recording is enabled +// does not segfault the process. +'use strict'; +const common = require('../common'); +common.skipIfInspectorDisabled(); +common.skipIf32Bits(); + +const { strictEqual } = require('assert'); +const eyecatcher = 'nou, houdoe he?'; + +if (process.argv[2] === 'child') { + const { Session } = require('inspector'); + const { promisify } = require('util'); + const { registerAsyncHook } = process.binding('inspector'); + (async () => { + let enabled = 0; + registerAsyncHook(() => ++enabled, () => {}); + const session = new Session(); + session.connect(); + session.post = promisify(session.post); + await session.post('Debugger.enable'); + strictEqual(enabled, 0); + await session.post('Debugger.setAsyncCallStackDepth', { maxDepth: 42 }); + strictEqual(enabled, 1); + throw new Error(eyecatcher); + })(); +} else { + const { spawnSync } = require('child_process'); + const options = { encoding: 'utf8' }; + const proc = spawnSync(process.execPath, [__filename, 'child'], options); + strictEqual(proc.status, 0); + strictEqual(proc.signal, null); + strictEqual(proc.stderr.includes(eyecatcher), true); +}