@@ -195,11 +195,13 @@ impl RpcSessionRef {
195195 /// take ownership of) file descriptors already connected to it.
196196 pub fn setup_preconnected_client < T : FromIBinder + ?Sized > (
197197 & self ,
198- mut request_fd : impl FnMut ( ) -> Option < RawFd > ,
198+ request_fd : impl FnMut ( ) -> Option < RawFd > ,
199199 ) -> Result < Strong < T > , StatusCode > {
200- // Double reference the factory because trait objects aren't FFI safe.
201- let mut request_fd_ref: RequestFd = & mut request_fd;
202- let param = & mut request_fd_ref as * mut RequestFd as * mut c_void ;
200+ // Trait objects aren't FFI safe, so *mut c_void can't be converted back to
201+ // *mut dyn FnMut() -> Option<RawFd>>. Double box the factory to make it possible to get
202+ // the factory from *mut c_void (to *mut Box<dyn<...>>) in the callbacks.
203+ let request_fd_box: Box < dyn FnMut ( ) -> Option < RawFd > > = Box :: new ( request_fd) ;
204+ let param = Box :: into_raw ( Box :: new ( request_fd_box) ) as * mut c_void ;
203205
204206 // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the
205207 // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership
@@ -209,6 +211,7 @@ impl RpcSessionRef {
209211 self . as_ptr ( ) ,
210212 Some ( request_fd_wrapper) ,
211213 param,
214+ Some ( param_delete_fd_wrapper) ,
212215 ) )
213216 } ;
214217 Self :: get_interface ( service)
@@ -225,13 +228,18 @@ impl RpcSessionRef {
225228 }
226229}
227230
228- type RequestFd < ' a > = & ' a mut dyn FnMut ( ) -> Option < RawFd > ;
229-
230231unsafe extern "C" fn request_fd_wrapper ( param : * mut c_void ) -> c_int {
231- let request_fd_ptr = param as * mut RequestFd ;
232+ let request_fd_ptr = param as * mut Box < dyn FnMut ( ) -> Option < RawFd > > ;
232233 // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the
233234 // BinderFdFactory reference, with param being a properly aligned non-null pointer to an
234235 // initialized instance.
235236 let request_fd = unsafe { request_fd_ptr. as_mut ( ) . unwrap ( ) } ;
236237 request_fd ( ) . unwrap_or ( -1 )
237238}
239+
240+ unsafe extern "C" fn param_delete_fd_wrapper ( param : * mut c_void ) {
241+ // SAFETY: This is only ever called by RpcPreconnectedClient, with param being the
242+ // pointer returned from Box::into_raw.
243+ let request_fd_box = unsafe { Box :: from_raw ( param as * mut Box < dyn FnMut ( ) -> Option < RawFd > > ) } ;
244+ drop ( request_fd_box) ;
245+ }
0 commit comments