Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inspector crash on "step into" async function #31419

Closed
Dragiyski opened this issue Jan 20, 2020 · 2 comments
Closed

Inspector crash on "step into" async function #31419

Dragiyski opened this issue Jan 20, 2020 · 2 comments
Labels
inspector Issues and PRs related to the V8 inspector protocol

Comments

@Dragiyski
Copy link

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.

@addaleax addaleax added the inspector Issues and PRs related to the V8 inspector protocol label Jan 20, 2020
@addaleax
Copy link
Member

Thanks for the report! @nodejs/v8-inspector

due to errors in GCC build of slow checks

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
Copy link
Author

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 of emitInitNative, 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 for emitInitNative is a little bit annoying, but not as disruptive as crash during debugging.

For example a function defined as:

async function test() { ... }

would have call stack after step-into, step-out, step-into (again) on a call statement test():

at test (/usr/src/test/test-async.js:5:18)
at Object.<anonymous> (/usr/src/test/test-async.js:10:1)

Therefore going through the emitInitNative does not affect stack frames;

After the first await, the stack becomes::

at test (/usr/src/test/test-async.js:6:18)
-- await in test (async) --
at Object.<anonymous> (/usr/src/test/test-async.js:10:1)

As the current version of the master is v14.0.0-pre I 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.12 from 7.9.317.25-node.30.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
inspector Issues and PRs related to the V8 inspector protocol
Projects
None yet
Development

No branches or pull requests

2 participants