mirror of
https://github.com/rust-mobile/android-activity.git
synced 2026-07-04 05:47:26 +00:00
Drop Weak<WaitableNativeActivityState> in on_destroy
When we know we're done with the `Weak` reference that is associated with the `NativeActivity` callbacks we make sure to drop the `Weak` reference so that the underlying allocation for the `WaitableNativeActivityState` can be freed. This also updates `try_with_waitable_activity_ref` to be more careful about converting the `Weak` ref back into a raw pointer _before_ calling the handler, just in case the handler triggers a panic and unwinds (where we wouldn't want to lose/Drop our weak ref).
This commit is contained in:
@@ -328,7 +328,7 @@ impl NativeActivityState {
|
||||
|
||||
impl Drop for WaitableNativeActivityState {
|
||||
fn drop(&mut self) {
|
||||
log::debug!("WaitableNativeActivityState::drop!");
|
||||
log::info!("WaitableNativeActivityState::drop!");
|
||||
unsafe {
|
||||
let mut guard = self.mutex.lock().unwrap();
|
||||
guard.detach_input_queue_from_looper();
|
||||
@@ -670,12 +670,19 @@ unsafe fn try_with_waitable_activity_ref(
|
||||
assert!(!(*activity).instance.is_null());
|
||||
let weak_ptr: *const WaitableNativeActivityState = (*activity).instance.cast();
|
||||
let weak_ref = Weak::from_raw(weak_ptr);
|
||||
if let Some(waitable_activity) = weak_ref.upgrade() {
|
||||
let maybe_upgraded = weak_ref.upgrade();
|
||||
|
||||
// Make sure we don't Drop the Weak reference (even if we failed to upgrade it
|
||||
// and also considering the possibility that we unwind due to a panic in `closure()`)
|
||||
// (The raw weak pointer associated with activity->instance must remain valid
|
||||
// until `on_destroy` is called).
|
||||
let _ = weak_ref.into_raw();
|
||||
|
||||
if let Some(waitable_activity) = maybe_upgraded {
|
||||
closure(waitable_activity);
|
||||
} else {
|
||||
log::error!("Ignoring spurious JVM callback after last activity reference was dropped!")
|
||||
}
|
||||
let _ = weak_ref.into_raw();
|
||||
}
|
||||
|
||||
unsafe extern "C" fn on_destroy(activity: *mut ndk_sys::ANativeActivity) {
|
||||
@@ -684,6 +691,16 @@ unsafe extern "C" fn on_destroy(activity: *mut ndk_sys::ANativeActivity) {
|
||||
try_with_waitable_activity_ref(activity, |waitable_activity| {
|
||||
waitable_activity.notify_destroyed()
|
||||
});
|
||||
|
||||
// Once we return from here the `ANativeActivity` will be deleted via an
|
||||
// `unloadNativeCode` native method and so we can't get any more
|
||||
// callbacks and we can release the `Weak<WaitableNativeActivityState>`
|
||||
// reference we have associated with `activity->instance`
|
||||
|
||||
assert!(!(*activity).instance.is_null());
|
||||
let weak_ptr: *const WaitableNativeActivityState = (*activity).instance.cast();
|
||||
let _drop_weak_ref = Weak::from_raw(weak_ptr);
|
||||
(*activity).instance = std::ptr::null_mut();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user