Change callback handling from Arc to Box
There is only ever one ref count for this callback object, and it's
always completely dropped when the Accessor or AccessorProvider objects
are dropped, so Box is a better type.
Test: atest rustBinderTest # has the *callback_destruction tests
Bug: 358427181
Change-Id: Ifc4b17a589b27f232c20c7e8a82d2b23a717fda8
diff --git a/libs/binder/rust/src/system_only.rs b/libs/binder/rust/src/system_only.rs
index 288c54b..50aa336 100644
--- a/libs/binder/rust/src/system_only.rs
+++ b/libs/binder/rust/src/system_only.rs
@@ -23,7 +23,7 @@
use std::os::raw::c_char;
use libc::{sockaddr, sockaddr_un, sockaddr_vm, socklen_t};
-use std::sync::Arc;
+use std::boxed::Box;
use std::{mem, ptr};
/// Rust wrapper around ABinderRpc_Accessor objects for RPC binder service management.
@@ -65,7 +65,7 @@
where
F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
{
- let callback: *mut c_void = Arc::into_raw(Arc::new(callback)) as *mut c_void;
+ let callback: *mut c_void = Box::into_raw(Box::new(callback)) as *mut c_void;
let inst = CString::new(instance).unwrap();
// Safety: The function pointer is a valid connection_info callback.
@@ -149,7 +149,7 @@
/// the string within isize::MAX from the pointer. The memory must not be mutated for
/// the duration of this function call and must be valid for reads from the pointer
/// to the null terminator.
- /// - The `cookie` parameter must be the cookie for an `Arc<F>` and
+ /// - The `cookie` parameter must be the cookie for a `Box<F>` and
/// the caller must hold a ref-count to it.
unsafe extern "C" fn connection_info<F>(
instance: *const c_char,
@@ -162,7 +162,7 @@
log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!");
return ptr::null_mut();
}
- // Safety: The caller promises that `cookie` is for an Arc<F>.
+ // Safety: The caller promises that `cookie` is for a Box<F>.
let callback = unsafe { (cookie as *const F).as_ref().unwrap() };
// Safety: The caller in libbinder_ndk will have already verified this is a valid
@@ -207,19 +207,19 @@
}
}
- /// Callback that decrements the ref-count.
+ /// Callback that drops the `Box<F>`.
/// This is invoked from C++ when a binder is unlinked.
///
/// # Safety
///
- /// - The `cookie` parameter must be the cookie for an `Arc<F>` and
+ /// - The `cookie` parameter must be the cookie for a `Box<F>` and
/// the owner must give up a ref-count to it.
unsafe extern "C" fn cookie_decr_refcount<F>(cookie: *mut c_void)
where
F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
{
- // Safety: The caller promises that `cookie` is for an Arc<F>.
- unsafe { Arc::decrement_strong_count(cookie as *const F) };
+ // Safety: The caller promises that `cookie` is for a Box<F>.
+ unsafe { std::mem::drop(Box::from_raw(cookie as *mut F)) };
}
}
@@ -296,7 +296,7 @@
where
F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
{
- let callback: *mut c_void = Arc::into_raw(Arc::new(provider)) as *mut c_void;
+ let callback: *mut c_void = Box::into_raw(Box::new(provider)) as *mut c_void;
let c_str_instances: Vec<CString> =
instances.iter().map(|s| CString::new(s.as_bytes()).unwrap()).collect();
let mut c_instances: Vec<*const c_char> =
@@ -346,7 +346,7 @@
log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!");
return ptr::null_mut();
}
- // Safety: The caller promises that `cookie` is for an Arc<F>.
+ // Safety: The caller promises that `cookie` is for a Box<F>.
let callback = unsafe { (cookie as *const F).as_ref().unwrap() };
let inst = {
@@ -377,14 +377,14 @@
///
/// # Safety
///
- /// - The `cookie` parameter must be the cookie for an `Arc<F>` and
+ /// - The `cookie` parameter must be the cookie for a `Box<F>` and
/// the owner must give up a ref-count to it.
unsafe extern "C" fn accessor_cookie_decr_refcount<F>(cookie: *mut c_void)
where
F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
{
- // Safety: The caller promises that `cookie` is for an Arc<F>.
- unsafe { Arc::decrement_strong_count(cookie as *const F) };
+ // Safety: The caller promises that `cookie` is for a Box<F>.
+ unsafe { std::mem::drop(Box::from_raw(cookie as *mut F)) };
}
}