Skip to content

Commit

Permalink
Gracefully handle isolate exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
kevmoo committed Mar 21, 2018
1 parent 8185fd9 commit c33f920
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 9 deletions.
2 changes: 2 additions & 0 deletions webdev/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

- Checks for a dependency on `build_web_compilers`.

- Gracefully handle exceptions.

## 0.1.0

- Initial release. Supports basic invocation of `build` and `serve` with
Expand Down
5 changes: 5 additions & 0 deletions webdev/bin/webdev.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'dart:async';
import 'dart:io';
import 'dart:isolate';

import 'package:args/command_runner.dart';
import 'package:io/ansi.dart';
Expand Down Expand Up @@ -35,5 +36,9 @@ Future main(List<String> args) async {
print(' ${e.path}');
}
exitCode = ExitCode.config.code;
} on IsolateSpawnException catch (e) {
print(red.wrap('An unexpected exception has occurred.'));
print(e.message);
exitCode = ExitCode.software.code;
}
}
33 changes: 24 additions & 9 deletions webdev/lib/src/command/build_runner_command_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,18 @@ abstract class BuildRunnerCommandBase extends Command<int> {
stderr.writeln(new Trace.parse(trace).terse);
if (exitCode == 0) exitCode = 1;
});
await Isolate.spawnUri(buildRunnerScript, arguments, messagePort.sendPort,
onExit: exitPort.sendPort,
onError: errorPort.sendPort,
automaticPackageResolution: true);

try {
await Isolate.spawnUri(buildRunnerScript, arguments, messagePort.sendPort,
onExit: exitPort.sendPort,
onError: errorPort.sendPort,
automaticPackageResolution: true);
} on IsolateSpawnException {
exitPort.close();
errorPort.close();
messagePort.close();
rethrow;
}
StreamSubscription exitCodeListener;
exitCodeListener = messagePort.listen((isolateExitCode) {
if (isolateExitCode is! int) {
Expand Down Expand Up @@ -90,11 +98,18 @@ Future<Uri> _buildRunnerScript() async {
var exitPort = new ReceivePort();
var errorPort = new ReceivePort();

await Isolate.spawnUri(dataUri, [], messagePort.sendPort,
onExit: exitPort.sendPort,
onError: errorPort.sendPort,
errorsAreFatal: true,
packageConfig: new Uri.file(_packagesFileName));
try {
await Isolate.spawnUri(dataUri, [], messagePort.sendPort,
onExit: exitPort.sendPort,
onError: errorPort.sendPort,
errorsAreFatal: true,
packageConfig: new Uri.file(_packagesFileName));
} on IsolateSpawnException {
messagePort.close();
exitPort.close();
errorPort.close();
rethrow;
}

var allErrorsFuture = errorPort.forEach((error) {
var errorList = error as List;
Expand Down
30 changes: 30 additions & 0 deletions webdev/test/integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,34 @@ packages:
contains('A `.packages` file does not exist in the target directory.'));
await process.shouldExit(78);
});

test('should fail gracefully if there is an isolate error', () async {
await d.file('pubspec.lock', '''
# Copy-pasted from a valid run
packages:
build_runner:
dependency: "direct main"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.0"
build_web_compilers:
dependency: "direct main"
description:
name: build_web_compilers
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.4+2"
''').create();

await d.file('.packages', '').create();

var process = await TestProcess.start('dart', [_webdevBin, 'build'],
workingDirectory: d.sandbox);
var output = (await process.stdoutStream().join('\n')).trim();

expect(output, contains('An unexpected exception has occurred.'));
await process.shouldExit(70);
});
}

0 comments on commit c33f920

Please sign in to comment.