Commit aac8762a authored by Todd Volkert's avatar Todd Volkert Committed by GitHub

Properly handle `ProcessExit` being thrown when `exit()` is called (#8592)

parent 96ccad53
......@@ -182,7 +182,12 @@ Future<int> _handleToolError(
return _exit(error.exitCode ?? 1);
} else if (error is ProcessExit) {
// We've caught an exit code.
return _exit(error.exitCode);
if (error.immediate) {
exit(error.exitCode);
return error.exitCode;
} else {
return _exit(error.exitCode);
}
} else {
// We've crashed; emit a log report.
stderr.writeln();
......@@ -217,7 +222,11 @@ Future<int> _handleToolError(
'Unable to generate crash report due to secondary error: $error\n'
'please let us know at https://github.com/flutter/flutter/issues.',
);
return _exit(1);
// Any exception throw here (including one thrown by `_exit()`) will
// get caught by our zone's `onError` handler. In order to avoid an
// infinite error loop, we throw an error that is recognized above
// and will trigger an immediate exit.
throw new ProcessExit(1, immediate: true);
}
}
}
......@@ -299,9 +308,13 @@ Future<int> _exit(int code) async {
// Give the task / timer queue one cycle through before we hard exit.
Timer.run(() {
printTrace('exiting with code $code');
exit(code);
completer.complete();
try {
printTrace('exiting with code $code');
exit(code);
completer.complete();
} catch (error, stackTrace) {
completer.completeError(error, stackTrace);
}
});
await completer.future;
......
......@@ -25,10 +25,12 @@
/// about any additional exports that you add to this file, as doing so will
/// increase the API surface that we have to test in Flutter tools, and the APIs
/// in `dart:io` can sometimes be hard to use in tests.
import 'dart:io' as io show exit, exitCode;
import 'dart:io' as io show exit;
import 'package:meta/meta.dart';
import 'process.dart';
export 'dart:io'
show
BytesBuilder,
......@@ -88,7 +90,7 @@ ExitFunction get exit => _exitFunction;
@visibleForTesting
void setExitFunctionForTests([ExitFunction exitFunction]) {
_exitFunction = exitFunction ?? (int exitCode) {
throw new Exception('Exited with code ${io.exitCode}');
throw new ProcessExit(exitCode, immediate: true);
};
}
......
......@@ -295,8 +295,9 @@ String _runWithLoggingSync(List<String> cmd, {
}
class ProcessExit implements Exception {
ProcessExit(this.exitCode);
ProcessExit(this.exitCode, {this.immediate: false});
final bool immediate;
final int exitCode;
String get message => 'ProcessExit: $exitCode';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment