You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
docs should clearly detail that objective-c callbacks are scoped to an isolate #3264
Yes, and the documentation should state that you should unregister your native callbacks on isolate exit. This can be done via NativeFinalizer.
E.g. if you do an HTTP request, and the native code is going to stream packets to Dart. In your NativeFinalizer you need to call your native cancel_http_request so that it stops streaming packets to Dart and stops doing callbacks.
Side note: The native finalizer approach will not work properly yet on Flutter with hot restart on helper isolates if you have singletons. E.g. if you have a native_register and native_unregister, and you call unregister on a helper isolate when it is shut down, then a new helper isolate might be started before the old helper isolate has shut down. Calling you to call native_register first, which is probably undefined behavior for your native code. More details: flutter/flutter#75528 (comment)
Yes, and the documentation should state that you should unregister your native callbacks on isolate exit. This can be done via NativeFinalizer.
E.g. if you do an HTTP request, and the native code is going to stream packets to Dart. In your NativeFinalizer you need to call your native cancel_http_request so that it stops streaming packets to Dart and stops doing callbacks.
I think that the premise of our objective-c interop is that the user does not have to write native code
Wouldn't cancel_http_request (or whatever) be racy, i.e., if the callback is dispatched after the isolate becomes unuseable before the finalizer completes?
Side note: The native finalizer approach will not work properly yet on Flutter with hot restart on helper isolates if you have singletons. E.g. if you have a native_register and native_unregister, and you call unregister on a helper isolate when it is shut down, then a new helper isolate might be started before the old helper isolate has shut down. Calling you to call native_register first, which is probably undefined behavior for your native code. More details: flutter/flutter#75528 (comment)
I think that the premise of our objective-c interop is that the user does not have to write native code
That's more of an aspiration than a premise. If this is a case where native code is necessary, so be it.
2. Wouldn't cancel_http_request (or whatever) be racy, i.e., if the callback is dispatched after the isolate becomes unuseable before the finalizer completes?
You'd need to make the finalizer blocking. The metadata entries aren't cleaned up until after the finalizers run, so blocking the final isolate cleanup until your HTTP client is confirmed closed should at least prevent crashes 1.
You could still have a memory leak if the callback is sending an object, and it never arrives (because the caller increments the ref count and the receiver decrements it). Hopefully this would be a rare edge case, because I'm struggling to think of a solution. Everything I think of just makes the edge case a bit more edgy.
Footnotes
The crash happens during callback dispatch, on the caller thread, where the callback's target port etc is looked up. If its metadata entry still exists then this will work fine even if the target isolate is mid-shutdown. The message will just silently never be handled. ↩
Activity
dcharkes commentedon Mar 26, 2026
Yes, and the documentation should state that you should unregister your native callbacks on isolate exit. This can be done via
NativeFinalizer.E.g. if you do an HTTP request, and the native code is going to stream packets to Dart. In your
NativeFinalizeryou need to call your nativecancel_http_requestso that it stops streaming packets to Dart and stops doing callbacks.Side note: The native finalizer approach will not work properly yet on Flutter with hot restart on helper isolates if you have singletons. E.g. if you have a
native_registerandnative_unregister, and you call unregister on a helper isolate when it is shut down, then a new helper isolate might be started before the old helper isolate has shut down. Calling you to callnative_registerfirst, which is probably undefined behavior for your native code. More details: flutter/flutter#75528 (comment)brianquinlan commentedon Mar 27, 2026
cancel_http_request(or whatever) be racy, i.e., if the callback is dispatched after the isolate becomes unuseable before the finalizer completes?liamappelbe commentedon Mar 30, 2026
That's more of an aspiration than a premise. If this is a case where native code is necessary, so be it.
You'd need to make the finalizer blocking. The metadata entries aren't cleaned up until after the finalizers run, so blocking the final isolate cleanup until your HTTP client is confirmed closed should at least prevent crashes 1.
You could still have a memory leak if the callback is sending an object, and it never arrives (because the caller increments the ref count and the receiver decrements it). Hopefully this would be a rare edge case, because I'm struggling to think of a solution. Everything I think of just makes the edge case a bit more edgy.
Footnotes
The crash happens during callback dispatch, on the caller thread, where the callback's target port etc is looked up. If its metadata entry still exists then this will work fine even if the target isolate is mid-shutdown. The message will just silently never be handled. ↩