Home > Mobile >  Dart Future: when throwing Error, the the main thread is interrupted, but in Flutter it's not
Dart Future: when throwing Error, the the main thread is interrupted, but in Flutter it's not

Time:06-19

I tried to test the behavior of future, but

Throwing an exception in future will break the dart main thread

However, the reverse is true in the Flutter:

Dart Code

   Future(() async {
                    await Future.delayed(Duration(seconds: 10));
                    print("TimeOut");
                  }).timeout(Duration(seconds: 5));

                  Future(() async {
                    await Future.delayed(Duration(seconds: 15));
                    print("AAAAAAA");
                  });

in Dart use the code dart run ./a.dart


Unhandled exception:
TimeoutException after 0:00:05.000000: Future not completed

in Flutter:

E/flutter (11789): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: TimeoutException after 0:00:05.000000: Future not completed
E/flutter (11789):
I/flutter (11789): TimeOut
I/flutter (11789): AAAAAAA

Why ?

CodePudding user response:

The difference between Dart and Flutter is that Flutter catches all unhandled exceptions and just prints them out (including the stack trace). This is on purpose and the secret is that Flutter registers a callback to the static class function FlutterError.onError and the default implementation is the function FlutterError.presentError. Some more details on the official docs: Handling errors in Flutter


Disable terminating on fatal errors in Dart

It's possible to disable terminating the app/script on fatal errors by calling Isolate.setErrorsFatal with false. For example, to keep async code running even if an unhandled exception is thrown just do this.

void main () {
  Isolate.current.setErrorsFatal(false); // <- Here

  Future(() async {
    await Future.delayed(Duration(seconds: 10));
    print("TimeOut");
  }).timeout(Duration(seconds: 5));

  Future(() async {
    await Future.delayed(Duration(seconds: 15));
    print("AAAAAAA");
  });
}

And the output is going to be:

TimeOut
AAAAAAA

Dart with the same behaviour as Flutter

The following code simulates the same thing Flutter does in Dart with runZonedGuarded:

import 'dart:async';

void main(List<String> args) {
  runZonedGuarded(program, errorHandler);
}

void program() {
  Future(() async {
    await Future.delayed(Duration(seconds: 10));
    print("TimeOut");
  }).timeout(Duration(seconds: 5));

  Future(() async {
    await Future.delayed(Duration(seconds: 15));
    print("AAAAAAA");
  });
}

void errorHandler(Object error, StackTrace stack) {
  print('Unhandled exception:\n$error');
}

The output is going to be the following in Dart:

Unhandled exception:
TimeoutException after 0:00:05.000000: Future not completed
TimeOut
AAAAAAA

Flutter with the same behaviour as Dart

On the other hand, it's possible to do the same thing in Flutter as Dart does. I.e. kills the app on whenever unhandled exception. It's just a matter of using the runZonedGuarded again:

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';

void main() {
  runZonedGuarded(() async {
    runApp(const MyApp());
  }, (Object error, StackTrace stack) {
    print('Unhandled exception:\n$error');
    exit(1);
  });
}

void program() {
  Future(() async {
    await Future.delayed(Duration(seconds: 10));
    print("TimeOut");
  }).timeout(Duration(seconds: 5));

  Future(() async {
    await Future.delayed(Duration(seconds: 15));
    print("AAAAAAA");
  });
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    program();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (context, child) => const Scaffold(
        body: Center(child: Text('The app is going to exit in 5 seconds...')),
      ),
    );
  }
}

The output is going to be the following:

flutter: Unhandled exception:
TimeoutException after 0:00:05.000000: Future not completed
Lost connection to device.
  • Related