From 0a4eba89f4eb521de400408d5cfde453a21845a3 Mon Sep 17 00:00:00 2001 From: Maciej Godek Date: Sun, 21 Mar 2021 23:56:29 +0100 Subject: [PATCH] Notify event pipe before releasing NativeActivity resources 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 correctly release various objects derived from the resource (e.g. `EGLSurface` from `NativeWindow`) before it goes away. Currently, the order is 2-3-1-4, which can lead to a deadlock or a race condition, if the user drops the read lock at some earlier point while continuing to use objects derived from the resource. This commit fixes the order. --- ndk-glue/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ndk-glue/src/lib.rs b/ndk-glue/src/lib.rs index 886bd031..b688b39c 100644 --- a/ndk-glue/src/lib.rs +++ b/ndk-glue/src/lib.rs @@ -260,8 +260,8 @@ unsafe extern "C" fn on_window_destroyed( activity: *mut ANativeActivity, _window: *mut ANativeWindow, ) { - *NATIVE_WINDOW.write().unwrap() = None; wake(activity, Event::WindowDestroyed); + *NATIVE_WINDOW.write().unwrap() = None; } unsafe extern "C" fn on_input_queue_created( @@ -279,10 +279,12 @@ unsafe extern "C" fn on_input_queue_destroyed( activity: *mut ANativeActivity, queue: *mut AInputQueue, ) { + wake(activity, Event::InputQueueDestroyed); let input_queue = InputQueue::from_ptr(NonNull::new(queue).unwrap()); + let mut input_queue_lock = INPUT_QUEUE.write().unwrap(); + assert!(input_queue_lock.as_ref().unwrap().ptr() == input_queue.ptr()); input_queue.detach_looper(); - *INPUT_QUEUE.write().unwrap() = None; - wake(activity, Event::InputQueueDestroyed); + *input_queue_lock = None; } unsafe extern "C" fn on_content_rect_changed(activity: *mut ANativeActivity, rect: *const ARect) {