nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
106.44k stars 29.01k forks source link

"There was an internal error in Node's debugger. Please report this bug." #8520

Closed jpolitz closed 6 years ago

jpolitz commented 7 years ago
⤇ node --version
v6.2.1
⤇ uname -a
Darwin prob 15.6.0 Darwin Kernel Version 15.6.0: Mon Aug 29 20:21:34 PDT 2016; root:xnu-3248.60.11~1/RELEASE_X86_64 x86_64

I got a crashing error in the debugger on the bt command. The whole trace is at the end of the report. Using iTerm2 3.0.8.

The file under test is pretty huge (20M), and is gnarly compiled output; I can provide it if it's helpful, along with instructions for running it (though it will be somewhat involved). I'm not totally sure how to begin isolating it to something smaller – I use the debugger in this way relatively frequently, and this is the first crash I've seen.

The sequence below seems to reliably cause the crash, but I haven't found a variation or shorter sequence that causes it. For example, I tried leaving out all the commands other than c and the setting and clearing of breakpoints, and the crash didn't happen.

Removing the --stack-trace-limit option doesn't change the behavior I see.

The sequence of debugger commands (summarized) was:

⤇ node debug --stack-trace-limit=1000 tests/pyret/tests/test-builtin-locator.jarr
debug> bt
debug> c
debug> sb(168435)
debug> c
debug> bt
debug> sb(810304)
debug> c
debug> cb("tests/pyret/tests/test-builtin-locator.jarr", 168435)
debug> c
debug> exec ann_check_temp14858
debug> exec R.GAS
debug> sb("tests/pyret/tests/test-builtin-locator.jarr", 168435)
debug> c
debug> bt
(node:44467) There was an internal error in Node's debugger. Please report this bug.
Path must be a string. Received undefined
TypeError: Path must be a string. Received undefined
    at assertPath (path.js:7:11)
    at Object.basename (path.js:1357:5)
    at _debugger.js:1174:22
    at _debugger.js:639:7
    at _debugger.js:294:5
    at Client._onResponse (_debugger.js:250:5)
    at Protocol.Client.protocol.onResponse (_debugger.js:163:39)
    at Protocol.execute (_debugger.js:121:14)
    at Client.<anonymous> (_debugger.js:160:14)
    at emitOne (events.js:96:13)
    at Client.emit (events.js:188:7)

The whole trace was:

⤇ node debug --stack-trace-limit=1000 tests/pyret/tests/test-builtin-locator.jarr
< Debugger listening on port 5858
connecting to 127.0.0.1:5858 ... ok
break in tests/pyret/tests/test-builtin-locator.jarr:1
> 1 if(typeof window === 'undefined') {
  2 requirejs = require("requirejs");
  3 define = requirejs.define;
debug> bt
#0 test-builtin-locator.jarr:1:63
debug> c
< There are 1 check blocks to run
< Running a check: {name: "freevars-e", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/ast-anf.arr", 788, 0, 29121, 798, 3, 29466)}
< Got a result: left(nothing)
< There are 2 check blocks to run
< Running a check: {name: "ConcatList", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/concat-lists.arr", 4, 0, 27, 146, 3, 5925)}
< Got a result: left(nothing)
< Running a check: {name: "check-block-1", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/concat-lists.arr", 216, 0, 8299, 219, 3, 8395)}
< Got a result: left(nothing)
< There are 1 check blocks to run
< Running a check: {name: "JExpr", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/js-ast.arr", 297, 0, 10037, 597, 3, 21257)}
< Got a result: left(nothing)
< There are 4 check blocks to run
< Running a check: {name: "desugar-scope-block", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/resolve-scope.arr", 204, 0, 7178, 354, 3, 13709)}
< Got a result: left(nothing)
< Running a check: {name: "desugar-scope", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/resolve-scope.arr", 430, 0, 17119, 503, 3, 20382)}
< Got a result: left(nothing)
< Running a check: {name: "scope-env-from-env", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/resolve-scope.arr", 522, 0, 21066, 531, 3, 21543)}
< Got a result: left(nothing)
< Running a check: {name: "check-unbound-ids-bad-assignments", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/resolve-scope.arr", 1134, 0, 49903, 1227, 3, 53651)}
< Got a result: left(nothing)
< There are 3 check blocks to run
< Running a check: {name: "ds-curry-nullary", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/desugar.arr", 220, 0, 6911, 232, 3, 7326)}
< Got a result: left(nothing)
< Running a check: {name: "ds-curry", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/desugar.arr", 245, 0, 7695, 312, 3, 9434)}
< Got a result: left(nothing)
< Running a check: {name: "desugar-expr", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/desugar.arr", 350, 0, 10293, 999, 3, 40081)}
< Got a result: left(nothing)
< There are 1 check blocks to run
< Running a check: {name: "check-block-1", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/src/arr/compiler/anf-loop-compiler.arr", 1483, 0, 56702, 1501, 3, 57416)}
< Got a result: left(nothing)
< Running builtin-locator tests: 1473789902735
< There are 2 check blocks to run
< Running a check: {name: "check-block-2", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/tests/pyret/tests/test-builtin-locator.arr", 11, 0, 341, 24, 3, 1161)}
< Got a result: left(nothing)
< Running a check: {name: "check-block-1", run: <function>, location: srcloc("file:///Users/joe/src/pyret-lang/tests/pyret/tests/test-builtin-locator.arr", 26, 0, 1163, 91, 3, 3253)}
< Building a worklist for: protocol://foo
< Dependencies: [list: dependency("protocol", [list: "bar"]), builtin("string-dict"), builtin("global"), builtin("base"), builtin("arrays"), builtin("lists"), builtin("option"), builtin("error"), builtin("sets")]
< Searching for: dependency("protocol", [list: "bar"])
< Found: protocol://bar
< Searching for: builtin("string-dict")
< Found: builtin://string-dict
< Searching for: builtin("global")
< Found: builtin://global
< Searching for: builtin("base")
< Found: builtin://base
< Searching for: builtin("arrays")
< Found: builtin://arrays
< Searching for: builtin("lists")
< Found: builtin://lists
< Searching for: builtin("option")
< Found: builtin://option
< Searching for: builtin("error")
< Found: builtin://error
< Searching for: builtin("sets")
< Found: builtin://sets
< Found mods: [list: "protocol://bar", "builtin://string-dict", "builtin://global", "builtin://base", "builtin://arrays", "builtin://lists", "builtin://option", "builtin://error", "builtin://sets"]
< Dependencies: [list: builtin("string-dict"), builtin("global"), builtin("base"), builtin("arrays"), builtin("lists"), builtin("option"), builtin("error"), builtin("sets")]
< Searching for: builtin("string-dict")
< Found: builtin://string-dict
< Searching for: builtin("global")
< Found: builtin://global
< Searching for: builtin("base")
< Found: builtin://base
< Searching for: builtin("arrays")
< Found: builtin://arrays
< Searching for: builtin("lists")
< Found: builtin://lists
< Searching for: builtin("option")
< Found: builtin://option
< Searching for: builtin("error")
< Found: builtin://error
< Searching for: builtin("sets")
< Found: builtin://sets
< Found mods: [list: "builtin://string-dict", "builtin://global", "builtin://base", "builtin://arrays", "builtin://lists", "builtin://option", "builtin://error", "builtin://sets"]
< Dependencies: [list: builtin("valueskeleton")]
< Searching for: builtin("valueskeleton")
< Found: builtin://valueskeleton
< Found mods: [list: "builtin://valueskeleton"]
< Dependencies: [list: builtin("global")]
< Searching for: builtin("global")
< Found: builtin://global
< Found mods: [list: "builtin://global"]
< Dependencies: [list: ]
< Found mods: [list: ]
< Done mapping
< Done mapping
< Done mapping
< Dependencies: [list: builtin("global"), builtin("option"), builtin("either"), builtin("error-display"), builtin("error"), builtin("equality"), builtin("valueskeleton"), builtin("lists"), builtin("arrays"), builtin("pick"), builtin("sets"), builtin("contracts"), builtin("srcloc"), builtin("render-error-display"), builtin("checker"), builtin("ffi"), builtin("table"), builtin("tables"), builtin("reactors"), builtin("data-source"), builtin("s-exp")]
< Searching for: builtin("global")
< Found: builtin://global
< Searching for: builtin("option")
< Found: builtin://option
< Searching for: builtin("either")
< Found: builtin://either
< Searching for: builtin("error-display")
< Found: builtin://error-display
< Searching for: builtin("error")
< Found: builtin://error
< Searching for: builtin("equality")
< Found: builtin://equality
< Searching for: builtin("valueskeleton")
< Found: builtin://valueskeleton
< Searching for: builtin("lists")
< Found: builtin://lists
< Searching for: builtin("arrays")
< Found: builtin://arrays
< Searching for: builtin("pick")
< Found: builtin://pick
< Searching for: builtin("sets")
< Found: builtin://sets
< Searching for: builtin("contracts")
< Found: builtin://contracts
< Searching for: builtin("srcloc")
< Found: builtin://srcloc
< Searching for: builtin("render-error-display")
< Found: builtin://render-error-display
< Searching for: builtin("checker")
break in tests/pyret/tests/test-builtin-locator.jarr:801002
 801000 R.ffi.throwNonFunApp($al789,dfind655);
 801001 }
>801002 if (d720.dict.modname === "checker") { debugger; }
 801003 $ans788 = dfind655.app(context665,d720);
 801004 if(R.isContinuation($ans788)) {
debug> sb(168435)
 800997 case 4: $step786 = 5;
 800998 $al789 = L[236];
 800999 if(!(R.isFunction(dfind655))) {
 801000 R.ffi.throwNonFunApp($al789,dfind655);
 801001 }
>801002 if (d720.dict.modname === "checker") { debugger; }
 801003 $ans788 = dfind655.app(context665,d720);
 801004 if(R.isContinuation($ans788)) {
 801005 debugger;
 801006 break;
 801007 }
debug> c
break in tests/pyret/tests/test-builtin-locator.jarr:168435
 168433
 168434       function deepCheckFields(remainingFields) {
>168435         var thisField;
 168436         return safeCall(function() {
 168437           thisField = remainingFields.pop();
debug> bt
#0 test-builtin-locator.jarr:168435:9
#1 PRecordAnn.check test-builtin-locator.jarr:168452:21
#2 test-builtin-locator.jarr:168052:22
#3 test-builtin-locator.jarr:168579:20
#4 test-builtin-locator.jarr:168051:16
#5 define.staticModules.file:///Users/joe/src/pyret-lang/src/arr/compiler/locators/builtin.arr.theModule.$temp_lam14251 test-builtin-locator.jarr:810303:3
#6 define.staticModules.file:///Users/joe/src/pyret-lang/tests/pyret/tests/test-builtin-locator.arr.theModule.$temp_lam14048 test-builtin-locator.jarr:811780:25
#7 define.staticModules.file:///Users/joe/src/pyret-lang/src/arr/compiler/compile-lib.arr.theModule.$temp_lam787 test-builtin-locator.jarr:801003:20
#8 test-builtin-locator.jarr:169630:23
#9 test-builtin-locator.jarr:169641:21
debug> sb(810304)
 168430           return that.createMissingFieldsError(compilerLoc, val);
 168431         }
 168432       }
 168433
 168434       function deepCheckFields(remainingFields) {
>168435         var thisField;
 168436         return safeCall(function() {
 168437           thisField = remainingFields.pop();
 168438           var thisChecker = that.anns[thisField];
 168439           return thisChecker.check(that.locs[that.locs.length - remainingFields.length], getColonField(val, thisField));
 168440         }, function(result) {
debug> c
break in tests/pyret/tests/test-builtin-locator.jarr:168435
 168433
 168434       function deepCheckFields(remainingFields) {
>168435         var thisField;
 168436         return safeCall(function() {
 168437           thisField = remainingFields.pop();
debug> cb("tests/pyret/tests/test-builtin-locator.jarr", 168435)
 168430           return that.createMissingFieldsError(compilerLoc, val);
 168431         }
 168432       }
 168433
 168434       function deepCheckFields(remainingFields) {
>168435         var thisField;
 168436         return safeCall(function() {
 168437           thisField = remainingFields.pop();
 168438           var thisChecker = that.anns[thisField];
 168439           return thisChecker.check(that.locs[that.locs.length - remainingFields.length], getColonField(val, thisField));
 168440         }, function(result) {
debug> c
break in tests/pyret/tests/test-builtin-locator.jarr:810304
 810302 $al14256 = L[200];
 810303 R._checkAnn(L[200],R.getDotAnn(L[200],"CL",CL59,"Locator"),ann_check_temp14858);
>810304 continue;
 810305 case 60: $step14250 = 61;
 810306 $ans14255 = ann_check_temp14858;
debug> exec ann_check_temp14858
{ dict:
   { 'get-modified-time':
      { meth: [Function],
        full_meth: [Function],
        arity: 1,
        name: 'get-modified-time',
        dict: {},
        brands: [Object] },
     'get-options':
      { meth: [Function],
        full_meth: [Function],
        arity: 2,
        name: 'get-options',
        dict: {},
        brands: [Object] },
     'get-module':
      { meth: [Function],
        full_meth: [Function],
        arity: 1,
        name: 'get-module',
        dict: {},
        brands: [Object] },
     'get-dependencies':
      { meth: [Function],
        full_meth: [Function],
        arity: 1,
        name: 'get-dependencies',
        dict: {},
        brands: [Object] },
     'get-native-modules':
      { meth: [Function],
        full_meth: [Function],
        arity: 1,
        name: 'get-native-modules',
        dict: {},
        brands: [Object] },
     'get-extra-imports':
      { meth: [Function],
        full_meth: [Function],
        arity: 1,
        name: 'get-extra-imports',
        dict: {},
        brands: [Object] },
     'get-globals':
      { meth: [Function],
        full_meth: [Function],
        arity: 1,
        name: 'get-globals',
        dict: {},
        brands: [Object] },
     'set-compiled':
      { meth: [Function],
        full_meth: [Function],
        arity: 3,
        name: 'set-compiled',
        dict: {},
        brands: [Object] },
     'needs-compile':
      { meth: [Function],
        full_meth: [Function],
        arity: 2,
        name: 'needs-compile',
        dict: {},
        brands: [Object] },
     'get-compiled':
      { meth: [Function],
        full_meth: [Function],
        arity: 1,
        name: 'get-compiled',
        dict: {},
        brands: [Object] },
     uri:
      { meth: [Function],
        full_meth: [Function],
        arity: 1,
        name: 'uri',
        dict: {},
        brands: [Object] },
     name:
      { meth: [Function],
        full_meth: [Function],
        arity: 1,
        name: 'name',
        dict: {},
        brands: [Object] },
     _equals:
      { meth: [Function],
        full_meth: [Function],
        arity: 3,
        name: '_equals',
        dict: {},
        brands: [Object] } },
  brands: { brandCount: 0 } }
debug> exec R.GAS
7
debug> sb("tests/pyret/tests/test-builtin-locator.jarr", 168435)
 810299 continue;
 810300 case 59: var ann_check_temp14858 = $ans14255;
 810301 $step14250 = 60;
 810302 $al14256 = L[200];
 810303 R._checkAnn(L[200],R.getDotAnn(L[200],"CL",CL59,"Locator"),ann_check_temp14858);
>810304 continue;
 810305 case 60: $step14250 = 61;
 810306 $ans14255 = ann_check_temp14858;
 810307 continue;
 810308 case 61: ++R.GAS;
 810309 return $ans14255;
debug> c
break in tests/pyret/tests/test-builtin-locator.jarr:168435
 168433
 168434       function deepCheckFields(remainingFields) {
>168435         var thisField;
 168436         return safeCall(function() {
 168437           thisField = remainingFields.pop();
debug> bt
(node:44467) There was an internal error in Node's debugger. Please report this bug.
Path must be a string. Received undefined
TypeError: Path must be a string. Received undefined
    at assertPath (path.js:7:11)
    at Object.basename (path.js:1357:5)
    at _debugger.js:1174:22
    at _debugger.js:639:7
    at _debugger.js:294:5
    at Client._onResponse (_debugger.js:250:5)
    at Protocol.Client.protocol.onResponse (_debugger.js:163:39)
    at Protocol.execute (_debugger.js:121:14)
    at Client.<anonymous> (_debugger.js:160:14)
    at emitOne (events.js:96:13)
    at Client.emit (events.js:188:7)
jpolitz commented 7 years ago

Ah, figured it out. There was a function created by Function as part of the stack trace, which is causing the error because it doesn't have a source location. Here's a much simpler repro:

var synthf = Function("f", "return f() + 1");
var g = function() {
  return synthf(h);
}
var h = function() {
  console.log("In h");
  debugger;
  return 6;
}
console.log(g());
⤇ node debug ~/scratch/eval-fun.js
< Debugger listening on port 5858
connecting to 127.0.0.1:5858 ... ok
break in scratch/eval-fun.js:1
> 1 var synthf = Function("f", "return f() + 1");
  2 var g = function() {
  3   return synthf(h);
debug> c
< In h
break in scratch/eval-fun.js:7
  5 var h = function() {
  6   console.log("In h");
> 7   debugger;
  8   return 6;
  9 }
debug> bt
(node:45862) There was an internal error in Node's debugger. Please report this bug.
Path must be a string. Received undefined
TypeError: Path must be a string. Received undefined
    at assertPath (path.js:7:11)
    at Object.basename (path.js:1357:5)
    at _debugger.js:1174:22
    at _debugger.js:639:7
    at _debugger.js:294:5
    at Client._onResponse (_debugger.js:250:5)
    at Protocol.Client.protocol.onResponse (_debugger.js:163:39)
    at Protocol.execute (_debugger.js:121:14)
    at Client.<anonymous> (_debugger.js:160:14)
    at emitOne (events.js:96:13)
gireeshpunathil commented 6 years ago

@jpolitz - is this still outstanding? if so can you try with the latest?

bnoordhuis commented 6 years ago

This can be closed. The old debugger was deprecated in favor of the V8 inspector.

jpolitz commented 6 years ago

Thanks for following up. Confirmed that this works fine with node inspect.