Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the full stack trace for async execution

For a small example like

import 'dart:async';
import 'package:stack_trace/stack_trace.dart';

void main() {
  scheduleAsync();
}

void scheduleAsync() {
  new Future.delayed(new Duration(seconds: 1))
      .then((_) => runAsync());
}

void runAsync() {
  throw 'oh no!';
}

I get this stack trace. The furthest I can trace the call back is the runAsync() call in scheduleAsync(). There is no information left, that scheduleAsync was called from main.

Unhandled exception:
Uncaught Error: oh no!
Stack Trace:
#0      runAsync (file:///home/myuser/dart/playground/bin/stack_trace/main.dart:14:3)
#1      scheduleAsync. (file:///home/myuser/dart/playground/bin/stack_trace/main.dart:10:28)
#2      _RootZone.runUnary (dart:async/zone.dart:1155)
#3      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:484)
#4      _Future._propagateToListeners (dart:async/future_impl.dart:567)
#5      _Future._complete (dart:async/future_impl.dart:348)
#6      Future.Future.delayed. (dart:async/future.dart:228)
#7      Timer._createTimer. (dart:async-patch/timer_patch.dart:16)
#8      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:385)
#9      _handleMessage (dart:isolate-patch/timer_impl.dart:411)
#10     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:142)

#0      _rootHandleUncaughtError. (dart:async/zone.dart:886)
#1      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#2      _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#3      _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:96)
#4      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:392)
#5      _handleMessage (dart:isolate-patch/timer_impl.dart:411)
#6      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:142)

Process finished with exit code 255

Is there a way to get the full stack trace?

like image 323
Günter Zöchbauer Avatar asked Mar 12 '15 15:03

Günter Zöchbauer


People also ask

What is async stack traces?

Asynchronous stack traces allow you to inspect function calls beyond the current event loop. This is particularly useful because you can examine the scope of previously executed frames that are no longer on the event loop. This feature is currently an experiment and needs to be enabled.

How do I turn on stack trace?

If the Console view is not visible, go to the menu option Window -> Show View and select Console. and then select Java Stack Trace Console from the drop-down list.

How do you analyze a stack trace?

Analyze external stack tracesFrom the main menu, select Code | Analyze Stack Trace or Thread Dump. In the Analyze Stack Trace dialog that opens, paste the external stack trace or thread dump into the Put a stacktrace here: text area. Click OK. The stack trace is displayed in the Run tool window.

What is stack trace in Dart?

A StackTrace is intended to convey information to the user about the call sequence that triggered an exception. These objects are created by the runtime, it is not possible to create them programmatically.


1 Answers

The stack_trace package https://pub.dartlang.org/packages/stack_trace puts together the whole stack trace.

See also
- this blog post from a developer of the stack_trace package.
- http://news.dartlang.org/2016/01/unboxing-packages-stacktrace.html?m=1

import 'dart:async';
import 'package:stack_trace/stack_trace.dart';

void main() {
  Chain.capture(() {
    scheduleAsync(); // <= pass my code in Chain.capture
    }, onError: (error, stack) {
      print(error);
      print(stack);
    });
}

void scheduleAsync() {
  new Future.delayed(new Duration(seconds: 1))
      .then((_) => runAsync());
}

void runAsync() {
  throw 'oh no!';
}

produces this output which allows trace back to the first line in main.

oh no!
main.dart 19:3                                                runAsync
main.dart 15:28                                               scheduleAsync.
package:stack_trace/src/stack_zone_specification.dart 134:26  registerUnaryCallback..
package:stack_trace/src/stack_zone_specification.dart 210:15  StackZoneSpecification._run
package:stack_trace/src/stack_zone_specification.dart 134:18  registerUnaryCallback.
dart:async/zone.dart 902                                      _rootRunUnary
dart:async/zone.dart 804                                      _CustomZone.runUnary
dart:async/future_impl.dart 484                               _Future._propagateToListeners.handleValueCallback
dart:async/future_impl.dart 567                               _Future._propagateToListeners
dart:async/future_impl.dart 348                               _Future._complete
dart:async/future.dart 228                                    Future.Future.delayed.
package:stack_trace/src/stack_zone_specification.dart 210:15  StackZoneSpecification._run
package:stack_trace/src/stack_zone_specification.dart 124:52  registerCallback.
dart:async/zone.dart 891                                      _rootRun
dart:async/zone.dart 796                                      _CustomZone.run
dart:async/zone.dart 704                                      _CustomZone.runGuarded
dart:async/zone.dart 729                                      _CustomZone.bindCallback.
package:stack_trace/src/stack_zone_specification.dart 210:15  StackZoneSpecification._run
package:stack_trace/src/stack_zone_specification.dart 124:52  registerCallback.
dart:async/zone.dart 895                                      _rootRun
dart:async/zone.dart 796                                      _CustomZone.run
dart:async/zone.dart 704                                      _CustomZone.runGuarded
dart:async/zone.dart 729                                      _CustomZone.bindCallback.
dart:async-patch/timer_patch.dart 16                          Timer._createTimer.
dart:isolate-patch/timer_impl.dart 385                        _Timer._runTimers
dart:isolate-patch/timer_impl.dart 411                        _handleMessage
dart:isolate-patch/isolate_patch.dart 142                     _RawReceivePortImpl._handleMessage
===== asynchronous gap ===========================
dart:async/zone.dart 828                                      _CustomZone.registerUnaryCallback
dart:async/future_impl.dart 208                               _Future.then
main.dart 15:12                                               scheduleAsync
main.dart 6:18                                                main.
package:stack_trace/src/chain.dart 82:24                      Chain.capture.
dart:async/zone.dart 895                                      _rootRun
dart:async/zone.dart 796                                      _CustomZone.run
dart:async/zone.dart 1251                                     runZoned
package:stack_trace/src/chain.dart 80:20                      Chain.capture
main.dart 5:16                                                main
dart:isolate-patch/isolate_patch.dart 255                     _startIsolate.
dart:isolate-patch/isolate_patch.dart 142                     _RawReceivePortImpl._handleMessage


Process finished with exit code 0

Even more useful is the terse version

import 'dart:async';
import 'package:stack_trace/stack_trace.dart';

void main() {
  Chain.capture(() {
    scheduleAsync();
    }, onError: (error, stack) {
      print(error);
      print(new Trace.from(stack).terse);
    });
}

void scheduleAsync() {
  new Future.delayed(new Duration(seconds: 1))
      .then((_) => runAsync());
}

void runAsync() {
  throw 'oh no!';
}

which produces:

oh no!
main.dart 19:3       runAsync
main.dart 15:28      scheduleAsync.
===== asynchronous gap ===========================
dart:async           _Future.then
main.dart 15:12      scheduleAsync
main.dart 6:18       main.
package:stack_trace  Chain.capture
main.dart 5:16       main


Process finished with exit code 0

like image 103
Günter Zöchbauer Avatar answered Sep 29 '22 05:09

Günter Zöchbauer