terminate method

Future<void> terminate()

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();
}