Make `IsolateRunner.close` not keep the isolate alive if called more than once.
diff --git a/lib/isolate_runner.dart b/lib/isolate_runner.dart index 15e0f65..19a6233 100644 --- a/lib/isolate_runner.dart +++ b/lib/isolate_runner.dart
@@ -32,6 +32,11 @@ /// Future returned by [onExit]. Set when [onExit] is first read. Future<void>? _onExitFuture; + /// Future returned by [close]. + /// + /// Avoids hanging if calling [close] twice. + Future<void>? _closeFuture; + /// Create an [IsolateRunner] wrapper for [isolate] /// /// The preferred way to create an `IsolateRunner` is to use [spawn] @@ -78,9 +83,11 @@ /// life cycle. @override Future<void> close() { + var closeFuture = _closeFuture; + if (closeFuture != null) return closeFuture; var channel = SingleResponseChannel(); _commandPort.send(list2(_shutdown, channel.port)); - return channel.result.then(ignore); + return _closeFuture = channel.result.then(ignore); } /// Kills the isolate.
diff --git a/test/isolaterunner_test.dart b/test/isolaterunner_test.dart index a292eb5..52b2796 100644 --- a/test/isolaterunner_test.dart +++ b/test/isolaterunner_test.dart
@@ -10,15 +10,23 @@ const _ms = Duration(milliseconds: 1); void main() { - test('create-close', testCreateClose); + group('create-close', testCreateClose); test('create-run-close', testCreateRunClose); test('separate-isolates', testSeparateIsolates); group('isolate functions', testIsolateFunctions); } -Future testCreateClose() { - return IsolateRunner.spawn().then((IsolateRunner runner) { - return runner.close(); +void testCreateClose() { + test('simple', () { + return IsolateRunner.spawn().then((IsolateRunner runner) { + return runner.close(); + }); + }); + test('close twice', () async { + var runner = await IsolateRunner.spawn(); + await runner.close(); + // Shouldn't hang! + await runner.close(); }); }