Skip to content

Commit

Permalink
Throw exception when isolate exits without renewal indication. (#7288)
Browse files Browse the repository at this point in the history
  • Loading branch information
isoos authored Dec 12, 2023
1 parent 06736a2 commit b6ab945
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 28 deletions.
5 changes: 5 additions & 0 deletions app/lib/service/entrypoint/_isolate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ class IsolateRunner {
_isolates.add(isolate);
unawaited(isolate.done.then((_) async {
_isolates.remove(isolate);
// The `done` callback may happen on schedule renewal, instance shutdown,
// or unexpected exits. We only need to propagate the issue on the later.
if (!_closing && !isolate.markedForRenew) {
throw Exception('$id exited unexpectedly.');
}
}));
if (entryPoint != null) {
await isolate.spawnFn(
Expand Down
69 changes: 41 additions & 28 deletions app/test/service/entrypoint/isolate_runner_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,39 +100,52 @@ void main() {
final subs = logger.onRecord.listen((event) {
messages.add(event.message);
});
final runner = IsolateRunner.fn(
logger: logger,
servicesWrapperFn: (fn) => fn(),
kind: 'test',
entryPoint: _main3,
final uncaughtErrors = [];
final zone = Zone.current.fork(
specification: ZoneSpecification(
handleUncaughtError: (self, parent, zone, e, st) {
uncaughtErrors.add(e);
},
),
);
await runner.start(1);
await zone.run(() async {
final runner = IsolateRunner.fn(
logger: logger,
servicesWrapperFn: (fn) => fn(),
kind: 'test',
entryPoint: _main3,
);
await runner.start(1);

await Future.delayed(Duration(seconds: 1));
expect(
messages,
[
'About to start test isolate #1 ...',
'test isolate #1 started.',
'ERROR from test isolate #1',
'About to close test isolate #1 ...',
'test isolate #1 closed.',
],
);
// second isolate is not started
await Future.delayed(Duration(seconds: 7));
expect(
await Future.delayed(Duration(seconds: 1));
expect(
messages,
isNot(containsAll([
'About to start test isolate #2 ...',
'test isolate #2 started.',
'ERROR from test isolate #2',
'About to close test isolate #2 ...',
'test isolate #2 closed.',
])));
[
'About to start test isolate #1 ...',
'test isolate #1 started.',
'ERROR from test isolate #1',
'About to close test isolate #1 ...',
'test isolate #1 closed.',
],
);
// second isolate is not started
await Future.delayed(Duration(seconds: 7));
expect(
messages,
isNot(containsAll([
'About to start test isolate #2 ...',
'test isolate #2 started.',
'ERROR from test isolate #2',
'About to close test isolate #2 ...',
'test isolate #2 closed.',
])));

await runner.close();
await runner.close();
});
await subs.cancel();
expect(uncaughtErrors, hasLength(1));
final ex = uncaughtErrors.single;
expect(ex.toString(), contains('test isolate #1 exited unexpectedly'));
});
});
}
Expand Down

0 comments on commit b6ab945

Please sign in to comment.