-
Notifications
You must be signed in to change notification settings - Fork 112
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
Notify event pipe before releasing NativeActivity resources #134
Notify event pipe before releasing NativeActivity resources #134
Conversation
To be ever so slightly more specific, could you mention in the commit message that acquiring a writelock in step |
c9b8754
to
0a4eba8
Compare
In order to ensure validity of the raw pointers to Android's `ANativeWindow` handed out by `Window::raw_window_handle()`, the `EventLoop` will hold on to a read lock on the `NativeWindow` returned by `ndk_glue::native_window()` between receiving the `WindowCreated` event and the matching `WindowDestroyed` event from `ndk-glue`'s event pipe. Note that this commit depends on recent fixes to `ndk-glue`, specifically this PR rust-mobile/ndk#134. Previous versions of `ndk-glue` will cause this code to deadlock due to a concurrency bug.
In order to ensure validity of the raw pointers to Android's `ANativeWindow` handed out by `Window::raw_window_handle()`, the `EventLoop` will hold on to a read lock on the `NativeWindow` returned by `ndk_glue::native_window()` between receiving the `WindowCreated` event and the matching `WindowDestroyed` event from `ndk-glue`'s event pipe. Note that this commit depends on recent fixes to `ndk-glue`, specifically this PR rust-mobile/ndk#134. Previous versions of `ndk-glue` will cause this code to deadlock due to a concurrency bug.
0a4eba8
to
e1b6f86
Compare
The design of ndk-glue seems to imply that the user of a `NativeActivity` resource, e.g. `NativeWindow` obtained from `ndk_glue::native_window()`, should hold a read lock on the resource as long as they are using it. Therefore, ndk-glue's `NativeActivity` callbacks related to resource release should: (1) notify the user of upcoming resource release, (2) acquire a write lock on the handle, waiting for all read locks to be dropped, (3) drop the handle, (4) return from the callback. This allows the user to react and correctly release various objects derived from the resource (e.g. swapchains/surfaces from `NativeWindow`) before it goes away. Currently, the order is 2-3-1-4, which can lead to a deadlock (if the user holds on to a read guard) or a race condition (if they drop the read guard early). This commit fixes the order.
e1b6f86
to
47c7f1b
Compare
Ok, I think I fixed it. :) Apologies for the repeated force pushes, I can't focus today. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
This completes #134 by applying the same pointer-equality check in `on_input_queue_destroyed` to `on_window_destroyed`, and documents when the user should hold on to or release any of the `RWLock`s to ensure proper lifetimes for dependencies like surfaces in graphics APIs.
Currently, some
NativeActivity
callbacks (on_native_window_destroyed
,on_input_queue_destroyed
):(1) acquire a write lock on a static handle to the resource that is about to be destroyed, (2) drop the handle, (3) dispatch an asynchronous
Event
to the user on a UNIX pipe notifying of the release, (4) immediately return from the callback.This is incorrect according to
ANativeActivityCallbacks docs
. If the user is holding on to a read lock on the handle (as they should), there will be a deadlock. If the user does not have a read lock on the handle, there is a race condition, since Android may free the resource before the user cleans up all the objects derived from that resource (e.g.EGLSurface
fromNativeWindow
).In order to prevent races,
ndk_glue
should (1) notify users of upcoming resource release, so they can correctly clean up derived objects, and only then (2) acquire a write lock on the handle, (3) drop the handle, (4) return from the callback.Closes #117