stack_trace icon indicating copy to clipboard operation
stack_trace copied to clipboard

Trace.parse() does not correctly parse standard stacks in stderr from the Dart VM

Open DanTup opened this issue 3 years ago • 1 comments

If I run:

main() {
  throw 'test';
}

I get the output:

Unhandled exception:
test
#0      main (file:///Users/danny/Desktop/dart_sample/bin/trace.dart:2:3)
#1      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#2      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)

If I feed this into Trace.parse, it doesn't appear to parse correctly (it goes into Trace.parseFriendly, and that doesn't seem to handle this format):

import 'package:stack_trace/stack_trace.dart';

main() {
  final stderrOutput = '''
Unhandled exception:
test
#0      main (file:///Users/danny/Desktop/dart_sample/bin/trace.dart:2:3)
#1      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#2      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
'''
      .trim();

  final trace = Trace.parse(stderrOutput);
  for (final frame in trace.frames) {
    print('${frame.uri} ${frame.line}:${frame.column}');
  }
}

Outputs:

file:///Users/danny/Desktop/dart_sample null:null
file:///Users/danny/Desktop/dart_sample null:null
file:///Users/danny/Desktop/dart_sample null:null

The URIs and line/col don't seem to have been parsed correctly. Calling Trace.parseVm() works correctly, but I don't know for certain that the stack will always be from a VM and thought Trace.parse should handle this.

DanTup avatar Jan 12 '22 12:01 DanTup

Turns out this is triggered by the line Unhandled exception: which apparently looks like a friendly trace line.

I'm not sure if that's intended or not. I was hoping that would just become an unparsed frame. I'm only getting the full stderr output so don't know where the stack starts/ends and was hoping any non-frame parts would become unparsed frames.

I can probably work around this by trying to detect the platform and calling the relevant constructor, though perhaps there's a more restrictive way friendly constructors could be detected (or, there could be a boolean flag to opt-out of the friendly parsing (or allowing it to also handle these frames)?

DanTup avatar Jan 12 '22 12:01 DanTup

This is working as intended. This library parses the StackTrace.toString output. Example:

class C {
  void f() {
    g();
  }

  void g() {
    throw 'hi';
  }
}

void main() {
  try {
    C().f();
  } catch (e, st) {
    final trace = Trace.parse(st.toString()); // works
    print(trace);
  }
}

In SDK backends (VM, dart2js, dart2wasm) the errors caught at the top-level are reported as: the error object, stack trace, and maybe some lines before/after/in-between. The library does not try to parse these formats.

osa1 avatar Sep 19 '24 10:09 osa1