why do we have to exit from main with using exit(0) after using Isolates?

Viewed 204
import 'dart:io';
import 'dart:isolate';

Isolate? isolate;

void printX(SendPort sendPort) {
  print(sendPort);
}

void main() async {
  var receiverPort = ReceivePort();
  isolate = await Isolate.spawn(printX, receiverPort.sendPort);
  isolate!.kill(priority: Isolate.immediate);
  exit(0);
}

why do we have to do exit(0)?

I saw that if I do not exit with exit code then I get stuck like it is waiting for some input. although the isolate is killed.

1 Answers

It's not the Isolate that's keeping the process alive, per se; it's actually the ReceivePort. The ReceivePort doesn't "know" that the isolate has been killed, so it's still happily waiting for events to come along.

Calling receiverPort.close() is what will allow the process to end. In fact, you don't even technically need to kill the isolate in order for the process to end, as long as you close the stream.

Here's a full version of your code which terminates immediately:

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

Isolate? isolate;

void printX(SendPort sendPort) {
  print(sendPort);
}

void main() async {
  var receiverPort = ReceivePort();
  isolate = await Isolate.spawn(printX, receiverPort.sendPort);
  receiverPort.close();
}

Additional note: If there is a listener subscribed to the ReceivePort, and the listener cancels its subscription, then the ReceivePort will close on its own; however, it's designed to buffer incoming events until a listener is subscribed - so if no listener ever subscribes, it never closes itself.

So this code will also terminate:

void main() async {
  var receiverPort = ReceivePort();

  var subscription = receiverPort.listen((message) {});
  isolate = await Isolate.spawn(printX, receiverPort.sendPort);
  
  subscription.cancel();
}
Related