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

Inconsistent handling of an error thrown in an error handler on the VM #45617

Open
natebosch opened this issue Apr 7, 2021 · 1 comment
Open
Labels
area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends.

Comments

@natebosch
Copy link
Member

This is similar to #45616 but behavior is a little different on the VM.

Reproduction case:

import 'dart:async';

void main() {
  runZoned(() {
    somethingAsync();
  }, zoneSpecification: ZoneSpecification(handleUncaughtError: handleError));
}

void handleError(
    Zone _, ZoneDelegate __, Zone ___, Object error, StackTrace stackTrace) {
  print('I see the error: $error');
  throw 'extra error';
}

void somethingAsync() async {
  await Future.delayed(const Duration(seconds: 1));
  throw 'sad';
}

I would expect either the extra error to never surface back to the handleError callback, or for it to show up in an infinite loop.

What happens in practice it that it surfaces more than 1, but less than ∞ times. The number of times varies by Dart release.

In Dart 2.0.0 and 2.1.0 the output shows up 3 times:

I see the error: sad
I see the error: extra error
I see the error: extra error
I see the error: extra error
Unhandled exception:
extra error

Starting in Dart 2.2.0 the output shows up only 2 times:

I see the error: sad
I see the error: extra error
I see the error: extra error
Unhandled exception:
extra error

There is a similar version disparity in the behavior of an implementation without using async.

import 'dart:async';

void main() {
  runZoned(() {
    somethingAsync();
  }, zoneSpecification: ZoneSpecification(handleUncaughtError: handleError));
}

void handleError(
    Zone _, ZoneDelegate __, Zone ___, Object error, StackTrace stackTrace) {
  print('I see the error: $error');
  throw 'extra error';
}

void somethingAsync() {
  Future.delayed(const Duration(seconds: 1)).then((_) {
    throw 'sad';
  });
}

Here the output shows up 1 fewer times:

Dart 2.0.0 and 2.1.0:

I see the error: sad
I see the error: extra error
I see the error: extra error
Unhandled exception:
extra error

Dart 2.2.0 and above:

I see the error: sad
I see the error: extra error
Unhandled exception:
extra error

I think that that the non-async version in recent Dart versions has the best behavior. @lrhn - is this specified somewhere? Should we look at adding any tests for behavior of error handlers which throw themselves?

@natebosch natebosch added the area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. label Apr 7, 2021
@lrhn
Copy link
Member

lrhn commented Apr 8, 2021

It's unspecified.

We assume that uncaught error handlers don't throw, and don't use Zone.current, but do not enforce it.

dart-bot pushed a commit that referenced this issue Apr 21, 2021
…r parent zone.

Avoids infinite recursion when the uncaught error is handled by the same,
potentially still failing, uncaught error handler.

Bug: #45616, #45617
Change-Id: I60ee0f1220b7345f4a41e1f1b323b8da47ed326e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194402
Reviewed-by: Nate Bosch <nbosch@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Auto-Submit: Lasse R.H. Nielsen <lrn@google.com>
Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends.
Projects
None yet
Development

No branches or pull requests

2 participants