3

I'm having trouble tracking down why my dart program isn't terminating. I'm pretty sure it's something to do with either isolates, or stream controllers, and making sure they are closed, but I can't work out what the problem is.

On all of my StreamControllers i'm calling await streamControllerName.close();, but I think there is an isolate closing mechanism that I don't know about. Would there be any reason why the event loop isn't finishing and so the program isn't exiting? Difficult to give more details as the code is quite long.

テッド
  • 776
  • 9
  • 21
  • 1
    Do you have any ReceivePort open? – julemand101 Jan 11 '22 at 17:02
  • yes there are `n` receive ports open where `n` is the number of isolates i spawn. Do these need to be closed? – テッド Jan 11 '22 at 17:04
  • 2
    Yes, they need to be closed. At least in the main isolate. – julemand101 Jan 11 '22 at 17:06
  • 1
    legend. That sorted my problem! Thank you so much. If you add an answer i'll accept it. Is it potentially a source of memory leaks if the receive ports are left open, or are they automatically closed after a while? – テッド Jan 11 '22 at 17:12
  • They are not closed automatically, so you need to close them when you are done with them. But you can also just reuse them if you want since you can create as many `SendPort` you want pointing to a given `ReceivePort`. – julemand101 Jan 11 '22 at 17:15
  • Ok. So it could potentially be a memory leak if I were to leave them open when I don't want to reuse them? Not quite sure what you mean by pointing many send ports to a give receive port. I'm creating a load of channels for communication between the main isolate and worker isolates, but if I do `IsolateChannel.connectReceive(rPort)` multiple times on the same `rPort` object of type `ReceivePort`, I get `Bad state: Stream has already been listened to.` – テッド Jan 11 '22 at 17:21
  • 1
    What I mean is that the `sendPort` property on `ReceivePort` can be sent to as many isolates you want and at the same time. You can therefore have many isolates sending data to the same `ReceivePort` but you can only subscribe once on a `ReceivePort` (unless you make it a broadcast Stream. See the note in the documentation: https://api.dart.dev/stable/2.15.1/dart-isolate/ReceivePort-class.html). – julemand101 Jan 11 '22 at 17:28

1 Answers1

7

Dart programs stops when the main isolate has nothing left to do (so no code is executing and no events on the event or microtask queues) and nothing is subscribed to which can spawn events into the main isolate.

Besides Timer which can spawn delayed events, we have ReceivePort which allow us to send events into an isolate from another isolate. It should be noted that Dart does not keep track of the relationship between a ReceivePort and SendPort instances pointing to that ReceivePort.

This means that Dart does not know when a ReceivePort is no longer "in use" and it is therefore up to the developer to ensure closing any open ReceivePort by calling the close() method on each instance (notice that SendPort does not have any close() method) when they are no longer in use.

As long as there are any open ReceivePort in the main isolate, the program will continue running since an event might be spawned from one of these ReceivePort instances.

julemand101
  • 28,470
  • 5
  • 52
  • 48