terminate method
Cancel and force-kill the worker isolate.
Waits up to 5 seconds for the isolate to exit gracefully after cancel.
If the isolate does not exit in time, it is killed and counted as a
zombie (the Rust handle may leak because freeById is skipped to
avoid use-after-free on the Rust handle).
Implementation
Future<void> terminate() async {
await cancel();
// Ask the worker to exit cleanly. After cancel halts execution the
// worker is idle in its event loop; sending dispose lets it shut down
// gracefully so we avoid the zombie/skip-freeById path.
_sendPort?.send(_DisposeRequest(_nextId++));
if (_exitCompleter != null && !_exitCompleter!.isCompleted) {
final exited = await _exitCompleter!.future
.timeout(const Duration(seconds: 5))
.then((_) => true)
.onError((_, _) => false);
if (!exited) {
_zombieCount++;
if (_zombieCount >= _zombieWarningThreshold) {
developer.log(
'dart_monty_ffi: $_zombieCount zombie isolate(s) detected. '
'Rust MontyHandle(s) leaked. '
'Consider investigating long-running or stuck executions.',
name: 'dart_monty_ffi',
level: 900, // WARNING
);
}
_cleanupAfterCrashDisposal(skipFreeById: true);
return;
}
}
_cleanupAfterCrashDisposal();
}