Skip to content
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

Jni sometimes hangs the whole app when run in second engine (with workmanager plugin) #1865

Open
TheLastGimbus opened this issue Jan 5, 2025 · 2 comments

Comments

@TheLastGimbus
Copy link

TheLastGimbus commented Jan 5, 2025

Hi 👋

I'm making an app when i do some bluetooth stuff - and i want to periodically run the code in background, with workmanager plugin

The plugin opens a new flutterEngine in a worker, which has it's own separate Java thread (as far as i know), and runs Dart there. Sometimes, tasks are canceled, and then engine gets closed, without any callback to Dart about it, so there is no good way to gracefull close/release anything 😒 (but this may be fixed in future)

(This case, where it closed without letting my functions finish nicely, gave me especially lot of headaches, but i'm not sure if that's because of Jni or my own code problems)


For very long time, i had a problem that sometimes when i opened my app, it just freezed entirely and didn't got past splash screen, without force-stoping it later - presumably, because of my tasks (with their Jni stuff) running before (maybe while) app opening, and somehow breaking everything 💀

I suspect that Jni may not like being run twice etc, so I did my best to double-triple-quadriple check if there's any Dart already running by registering it in IsolateNameServer and later checking if someone's already registered (if it is, then do not run any Jni-related code):

I got this to work pretty well, but sometimes, i still get very deadly ANRs, probably when the worker and MainActivity start and end in some specific orders... I honestly don't know if, in those cases, any of my Jni code (like getAppContext()) actually runs, or it may be some problems with garbage collectors etc (i don't know if adding jni to my app while not running a line from it actually makes it autmatically run some inits and releases on it's own)

Here is an init() function from my libarary that uses Jni. I do not have any dispose()/close() function, because... i don't know if i should put any .release()s there or smth(?)

/~https://github.com/TheLastGimbus/the_last_bluetooth/blob/3a5314d2fdcd23585ecef8aecf8ee909b4cee775/lib/the_last_bluetooth.dart#L123-L177


Summarising all of this, it would be nice if I just... you know, could safely run them twice...

If i find some time, i may write a simple test app to make capturing this easier - for now, you can compile /~https://github.com/TheLastGimbus/FreeBuddy/tree/fb400c95214e9bb502dbb4d98d71e336bea3ae80 if you want, the errors should be present without actually having headphones 😂 - you could force the execution of background task by copy-pasting what's in BluetoothDeviceConnectedReceiver - /~https://github.com/TheLastGimbus/FreeBuddy/blob/fb400c95214e9bb502dbb4d98d71e336bea3ae80/android/app/src/main/kotlin/com/lastgimbus/the/freebuddy/BluetoothDeviceConnectedReceiver.kt#L58-L66 - and triggering it with some generic broadcast receiver (that could be triggered from adb), for example 👍


// All of this mayyy be somehow related to #970 ?

@HosseinYousefi
Copy link
Member

I suspect that Jni may not like being run twice etc,

I don't understand this!?

If i find some time, i may write a simple test app to make capturing this easier

That would be great.

I got this to work pretty well, but sometimes, i still get very deadly ANRs, probably when the worker and MainActivity start and end in some specific orders... I honestly don't know if, in those cases, any of my Jni code (like getAppContext())

Can you post specific error messages you get?


We could add hooks for onAttached/DetachedToEngine to call init/release code, however I first want to know exactly what you problem is.

@HosseinYousefi
Copy link
Member

I checked the initializing code and it sets the context on attached to engine. When you have a second engine running, it will override the context with another one which is incorrect causing the crash. I will have to store one context per engine to fix your problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

No branches or pull requests

2 participants