-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JObject.implement deadlocks #1908
Comments
Note that I'm having same issue with using ffi with |
Yes, that's why we didn't do this before. Maybe we can only do this when we detect that we're on the main isolate of a Flutter application where the thread is indeed pinned. cc @dcharkes @liamappelbe @mkustermann for ideas. |
Can you elaborate on this? Are you seeing a deadlock with
IIUC, jnigen does blocking callbacks similarly to ffigen, and there are 2 code paths. When the callback is coming from a random thread, it sends a message to the target isolate and waits for a reply. When the callback is coming from the same thread as the target isolate, the callback is invoked synchronously. And it sounds like the issue here is that the check that decides which code path to take is a bit unreliable on flutter. jnigen is using
Another option would be to discard the message sending code path entirely, and just enter the target isolate and invoke the callback synchronously. In fact, this is one of the
|
Apologies for confusion, perhaps shouldn't have mixed these under same issue. The // this works because dart_ffi_callback is called while isolate is active
void dart_ffi_callback(void (*isolate_local_trampoline)(void)) {
isolate_local_trampoline();
}
// this doesn't work, even though the trampoline is invoked on same thread, because
// the trampoline is invokedwhile pumping the dispatch queue and isolate is
// no longer active.
void dart_ffi_callback(void (*isolate_local_trampoline)(void)) {
dispatch_async(dispatch_get_main_queue(), ^{
// same thread, fails.
isolate_local_trampoline();
});
}
// This works again. This could be done automatically by the trampoline if we saved thread Id
// with the callback metadata, but it might be the wrong thing to do if we don't know that isolate
// is always running on a particular thread (i.e. like flutter UI thread).
void dart_ffi_callback(void (*isolate_local_trampoline)(void)) {
Dart_Isolate isolate = Dart_CurrentIsolate_DL();
dispatch_async(dispatch_get_main_queue(), ^{
Dart_EnterIsolate_DL(isolate);
isolate_local_trampoline();
Dart_ExitIsolate_DL(isolate);
});
} As far as I can tell, unlike jnigen, dart ffi trampolines never block? |
Java code
Dart code
Java Stack trace
Native Stack trace
The problem that
Java_com_github_dart_1lang_jni_PortProxyBuilder__1invoke
checksDart_CurrentIsolate_DL
to determine whether the call is coming from another thread, and if that returnsnull
it sends message on port and wait. However in case of Flutter on Android, the platform thread is the isolate thread, which means it is essentially blocking the main thread. Note thatDart_CurrentIsolate_DL
returnsnull
, because after posting the callback to main looper the isolate has been exited.The solution that would work in the context of Flutter is to remember the thread Id alongside isolate, and if the thread Id matches, calling
Dart_EnterIsolate_DL
andDart_ExitIsolate_DL
around the trampoline.Now while this works for Flutter, I'm not sure the solution is generic enough since it makes assumption about the isolate being "pinned" to a specific thread.
cc @HosseinYousefi
The text was updated successfully, but these errors were encountered: