Repository navigation
Inspector crash on "step into" async function #31419
Description
- Version: v13.6.0
- Platform: Linux dragiyski-laptop 4.15.0-72-generic fs: fix fd leak on early readstream destroy #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
- Subsystem: inspector
If a step into command is invoked on a method that is async function of an prototype, with closure scopes, the node crashes. Here is hypothetical code:
// module.js
module.exports = function someClosure() {
'use strict';
const path = require('path');
// ... other const values defined in this closure
function Class() {
}
Class.prototype = Object.create(Object.prototype, {
// Property definitions:
method: {
// Note: this occurred with non-configurable, non-writable function on the prototype
enumerable: true,
value: async function() { /* some code returning promise */ }
}
});
return Class;
};// index.js
const Class = require('./module')();
const instance = new Class();
// (1)Breakpoint on the next line
instance.method(/* ... some parameters ... */).then(/* ... */);When a breakpoint is set on the method call and "step into" command is issued, the inspector crashes. If no breakpoint is set on line (1), but a breakpoint is set within the method, inspector runs normally. Note that the crush occurs when "step into" command is issued. Breaking on the line of the call is not a problem. All function scopes and closures can be examined without causing a crash.
Running with the same version of nodejs, but with a debug build from source, the following output is obtained:
Debugger listening on ws://127.0.0.1:9229/a2d8d490-5a7a-429e-8f4f-dbf64005d986
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
#
# Fatal error in ../deps/v8/src/debug/debug-scopes.cc, line 132
# Debug check failed: (closure_scope_) != nullptr.
#
#
#
#FailureMessage Object: 0x7fffc820dc00
1: 0x55ab92ec75a9 node::DumpBacktrace(_IO_FILE*) [/home/dragiyski/opt/node-v13.6.0/bin/node]
2: 0x55ab9303c3cb [/home/dragiyski/opt/node-v13.6.0/bin/node]
3: 0x55ab9303c3eb [/home/dragiyski/opt/node-v13.6.0/bin/node]
4: 0x55ab9491a396 V8_Fatal(char const*, int, char const*, ...) [/home/dragiyski/opt/node-v13.6.0/bin/node]
5: 0x55ab9491a3c5 [/home/dragiyski/opt/node-v13.6.0/bin/node]
6: 0x55ab933bfd19 v8::internal::ScopeIterator::TryParseAndRetrieveScopes(v8::internal::ScopeIterator::Option) [/home/dragiyski/opt/node-v13.6.0/bin/node]
7: 0x55ab933bdaf1 v8::internal::DebugScopeIterator::DebugScopeIterator(v8::internal::Isolate*, v8::internal::FrameInspector*) [/home/dragiyski/opt/node-v13.6.0/bin/node]
8: 0x55ab933c96df v8::internal::DebugStackTraceIterator::GetScopeIterator() const [/home/dragiyski/opt/node-v13.6.0/bin/node]
9: 0x55ab93c3d128 v8_inspector::V8DebuggerAgentImpl::currentCallFrames(std::unique_ptr<std::vector<std::unique_ptr<v8_inspector::protocol::Debugger::CallFrame, std::default_delete<v8_inspector::protocol::Debugger::CallFrame> >, std::allocator<std::unique_ptr<v8_inspector::protocol::Debugger::CallFrame, std::default_delete<v8_inspector::protocol::Debugger::CallFrame> > > >, std::default_delete<std::vector<std::unique_ptr<v8_inspector::protocol::Debugger::CallFrame, std::default_delete<v8_inspector::protocol::Debugger::CallFrame> >, std::allocator<std::unique_ptr<v8_inspector::protocol::Debugger::CallFrame, std::default_delete<v8_inspector::protocol::Debugger::CallFrame> > > > > >*) [/home/dragiyski/opt/node-v13.6.0/bin/node]
10: 0x55ab93c44956 v8_inspector::V8DebuggerAgentImpl::didPause(int, v8::Local<v8::Value>, std::vector<int, std::allocator<int> > const&, v8::debug::ExceptionType, bool, bool, bool) [/home/dragiyski/opt/node-v13.6.0/bin/node]
11: 0x55ab93c2a11a [/home/dragiyski/opt/node-v13.6.0/bin/node]
12: 0x55ab93c5104c v8_inspector::V8InspectorImpl::forEachSession(int, std::function<void (v8_inspector::V8InspectorSessionImpl*)> const&) [/home/dragiyski/opt/node-v13.6.0/bin/node]
13: 0x55ab93c31b57 v8_inspector::V8Debugger::BreakProgramRequested(v8::Local<v8::Context>, std::vector<int, std::allocator<int> > const&) [/home/dragiyski/opt/node-v13.6.0/bin/node]
14: 0x55ab933db9eb v8::internal::Debug::OnDebugBreak(v8::internal::Handle<v8::internal::FixedArray>) [/home/dragiyski/opt/node-v13.6.0/bin/node]
15: 0x55ab933dbdb4 v8::internal::Debug::Break(v8::internal::JavaScriptFrame*, v8::internal::Handle<v8::internal::JSFunction>) [/home/dragiyski/opt/node-v13.6.0/bin/node]
16: 0x55ab939bae7a [/home/dragiyski/opt/node-v13.6.0/bin/node]
17: 0x55ab939bb42b v8::internal::Runtime_DebugBreakOnBytecode(int, unsigned long*, v8::internal::Isolate*) [/home/dragiyski/opt/node-v13.6.0/bin/node]
18: 0x55ab93ff3a40 [/home/dragiyski/opt/node-v13.6.0/bin/node]
Illegal instruction (core dumped)
Here is source information extracted for the most relevant frames:
#3: ../deps/v8/src/debug/debug-scopes.cc:132
#4: ../deps/v8/src/debug/debug-scopes.cc:107
#5: ../deps/v8/src/debug/debug-scopes.cc:260
P.S. The bug occurs in the release version v13.6.0, as downloaded by nvm or even when using prebuilt linux-x64 node from NodeJS downloads. The debug output here is shown from debug build from source, but without non-optimized debug V8 (due to errors in GCC build of slow checks). Thus currently bt does not provide source information, while frame provides a source location, but no source files. Therefore, I cannot show better trace than this.
Activity
addaleax commentedon Jan 20, 2020
Thanks for the report! @nodejs/v8-inspector
v8/v8@fc17585 solves that (e.g. through using
curl -L 'https://github.com/v8/v8/commit/fc1758579661a3831ab954a9b35aea61363187dc.patch' | git am --directory=deps/v8)Dragiyski commentedon Apr 11, 2020
Update: It seems this issues is fixed on master now. Instead of crash, the step into now enters
emitInitNative(probably called from C++). On step out ofemitInitNative, the execution goes into the async function. As expected the call stack does not contain any other frames between the caller and the async callee. Going through step into - step out cycle foremitInitNativeis a little bit annoying, but not as disruptive as crash during debugging.For example a function defined as:
would have call stack after step-into, step-out, step-into (again) on a call statement
test():Therefore going through the
emitInitNativedoes not affect stack frames;After the first
await, the stack becomes::As the current version of the master is
v14.0.0-preI do not suppose this fix would make it in v13.x?P.S. I do not see what fixed this. I suppose it is possible the fix came as V8 is not updated to
8.1.307.26-node.12from7.9.317.25-node.30.