rmawatson / flutter_isolate

Launch an isolate that can use flutter plugins.
MIT License
262 stars 80 forks source link

Isolate spawns only once #109

Closed Asored-D closed 2 years ago

Asored-D commented 2 years ago

Hi there, for some reason my Isolate spawns only once. After running the app it fires. But after each Hot Restart nothing happens.

Here is my code:

print('spawning isolate');
final flutterIsolate =
    await FlutterIsolate.spawn(spawnIsolate, "test") as FlutterIsolate;

final receivePort = ReceivePort();
final sendPort = receivePort.sendPort;
IsolateNameServer.registerPortWithName(sendPort, 'main');

receivePort.listen((dynamic message) {
  print("Done");
  print(message);

  flutterIsolate.kill();
});
Future<void> spawnIsolate(String data) async {
final port = IsolateNameServer.lookupPortByName('main');
  if (port != null) {
    port.send(data);
  } else {
    print('port is null');
  }
}

On the first app start I get the Done console log and the data result from the isolate. After each Hot Reload or Hot Restart it hangs on spawning isolate and I never get data from the listener.

By the way: I'm using the version 1.0.0+15 because its a non null safety app.

What could be the reason for that?

nmfisher commented 2 years ago

I have a feeling that hot restarts reinstantiate the main FlutterEngine but the flutter_isolate lifecycle listener doesn't recreate the appropriate channels, so those spawn messages go nowhere.

EDIT - above was wrong, ignore it, problem must be elsewhere.

This is probably fixable.

Asored-D commented 2 years ago

I have a feeling that hot restarts reinstantiate the main FlutterEngine but the flutter_isolate lifecycle listener doesn't recreate the appropriate channels, so those spawn messages go nowhere.

This is probably fixable.

Thanks very much for the fast reply! Because I had to fix the Hot Restart Crashing bug manually (the pull request already was a null safety version), I have a local version of the plugin. What do you think how that issue can be fixed? It is a hard task? :)

nmfisher commented 2 years ago

Which platform are you using (Android)? I will see if I can fix and you can help me test.

Asored-D commented 2 years ago

Which platform are you using (Android)? I will see if I can fix and you can help me test.

With pleasure :) I'm working on iOS and I test on a real device.

nmfisher commented 2 years ago

Can you create/share a repository with your sample code so I can easily reproduce the issue?

Asored-D commented 2 years ago

Can you create/share a repository with your sample code so I can easily reproduce the issue?

Unfortunately, I can't share the project I'm working on. But it would be way too big and confusing anyway. Basically, this should also work with a fresh Flutter project.

Important to mention would be the following features:

Flutter 1.22.2 - channel stable - https://github.com/flutter/flutter.git Framework - revision 84f3d28555 (1 year, and 8 months ago) - 2020-10-15 16:26:19 -0700 Engine - revision b8752bbfff Tools - Dart 2.10.2

.. and the flutter_isolate package version: 1.0.0+15

With these informations you should be able to reproduce the issue :)

nmfisher commented 2 years ago

That's fine, I meant can you create a new Flutter app and add the code you pasted so I can just clone and run straight away.

Asored-D commented 2 years ago

That's fine, I meant can you create a new Flutter app and add the code you pasted so I can just clone and run straight away.

I've created a repository with a new Flutter project with the same dependency situation as my live project. I get the same error. You can clone the following project: https://github.com/Asored-D/flutter-isolate-debug

Here again the Flutter version details:

Flutter 1.20.1 • channel stable • https://github.com/flutter/flutter.git Tools • Dart 2.9.0

Thanks! :)

nmfisher commented 2 years ago

I can't actually get that to run with Flutter 1.20.1 but at least I can reproduce the issue on later versions of Flutter.

What happens if you change:

IsolateNameServer.registerPortWithName(sendPort, 'main');

to

IsolateNameServer.removePortNameMapping('main');
IsolateNameServer.registerPortWithName(sendPort, 'main');

That fixes the issue for me but I don't know if that will apply to older versions of Flutter.

Asored-D commented 2 years ago

Great. It works with your solution. Many thanks. Thats really elegant. Is this also needed on a release version? (There no Hot Restarting exists). What do you think? Do I have performance problems or something else removing the port mapping each time I run the function?

nmfisher commented 2 years ago

This isn’t an issue with flutter_isolate, it looks like the underlying IsolateNameServer isn’t clearing registered ports on a hot restart. If you read the documentation for registerPortWithName you’ll see that it should return false if a port cannot be mapped - I suspect if you check this value in your original code, it was returning false after the hot restart.

I doubt you need this specific workaround but probably a good idea generally to check this return value every time you try and register a port.

On 4 Jun 2022, at 3:43 PM, Daniele De Rosa @.***> wrote:

 Great. It works with your solution. Many thanks. Thats really elegant. Is this also needed on a release version? (There no Hot Restarting exists). What do you think? Do I have performance problems or something else removing the port mapping each time I run the function?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.