diff --git a/drivers/android/binder/freeze.rs b/drivers/android/binder/freeze.rs index 318a9d2bb261..66912b4cb527 100644 --- a/drivers/android/binder/freeze.rs +++ b/drivers/android/binder/freeze.rs @@ -60,6 +60,7 @@ fn allow_duplicate(&self, node: &DArc) -> bool { /// Represents a notification that the freeze state has changed. pub(crate) struct FreezeMessage { cookie: FreezeCookie, + pid: i32, } kernel::list::impl_list_arc_safe! { @@ -73,8 +74,8 @@ fn new(flags: kernel::alloc::Flags) -> Result { UniqueArc::new_uninit(flags) } - fn init(ua: UninitFM, cookie: FreezeCookie) -> DLArc { - match ua.pin_init_with(DTRWrap::new(FreezeMessage { cookie })) { + fn init(ua: UninitFM, cookie: FreezeCookie, pid: i32) -> DLArc { + match ua.pin_init_with(DTRWrap::new(FreezeMessage { cookie, pid })) { Ok(msg) => ListArc::from(msg), Err(err) => match err {}, } @@ -140,7 +141,14 @@ fn do_work( } } - fn cancel(self: DArc) {} + fn cancel(self: DArc) { + binder_debug!( + pid = self.pid, + DeadTransaction, + "undelivered freeze notification, {:016x}", + self.cookie.0 + ); + } fn should_sync_wakeup(&self) -> bool { false @@ -258,7 +266,7 @@ pub(crate) fn request_freeze_notif( } *info.freeze() = Some(cookie); - let msg = FreezeMessage::init(msg, cookie); + let msg = FreezeMessage::init(msg, cookie, self.task.pid()); drop(node_refs_guard); let _ = self.push_work(msg); Ok(()) @@ -279,7 +287,7 @@ pub(crate) fn freeze_notif_done(self: &Arc, reader: &mut UserSliceReader) }; let mut clear_msg = None; if freeze.num_pending_duplicates > 0 { - clear_msg = Some(FreezeMessage::init(alloc, cookie)); + clear_msg = Some(FreezeMessage::init(alloc, cookie, self.task.pid())); freeze.num_pending_duplicates -= 1; freeze.num_cleared_duplicates += 1; } else { @@ -294,7 +302,7 @@ pub(crate) fn freeze_notif_done(self: &Arc, reader: &mut UserSliceReader) let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen(); if freeze.is_clearing || freeze.last_is_frozen != Some(is_frozen) { // Immediately send another FreezeMessage. - clear_msg = Some(FreezeMessage::init(alloc, cookie)); + clear_msg = Some(FreezeMessage::init(alloc, cookie, self.task.pid())); } freeze.is_pending = false; } @@ -347,7 +355,7 @@ pub(crate) fn clear_freeze_notif(self: &Arc, reader: &mut UserSliceReader) *info.freeze() = None; let mut msg = None; if !listener.is_pending { - msg = Some(FreezeMessage::init(alloc, cookie)); + msg = Some(FreezeMessage::init(alloc, cookie, self.task.pid())); } drop(node_refs_guard); @@ -427,7 +435,7 @@ pub(crate) fn prepare_freeze_messages(&self) -> Result) {} + fn cancel(self: DArc) { + binder_debug!( + pid = self.process.task.pid(), + DeadTransaction, + "undelivered death notification, {:016x}", + self.cookie + ); + } fn should_sync_wakeup(&self) -> bool { false diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs index 29829cb210a4..15c7b65928d8 100644 --- a/drivers/android/binder/rust_binder_main.rs +++ b/drivers/android/binder/rust_binder_main.rs @@ -221,6 +221,7 @@ fn arc_pin_init(init: impl PinInit) -> Result, kernel::error::Error> struct DeliverCode { code: u32, skip: Atomic, + pid: i32, } kernel::list::impl_list_arc_safe! { @@ -228,10 +229,11 @@ struct DeliverCode { } impl DeliverCode { - fn new(code: u32) -> Self { + fn new(code: u32, pid: i32) -> Self { Self { code, skip: Atomic::new(false), + pid, } } @@ -256,7 +258,15 @@ fn do_work( Ok(true) } - fn cancel(self: DArc) {} + fn cancel(self: DArc) { + if !self.skip.load(Relaxed) { + binder_debug!( + pid = self.pid, + DeadTransaction, + "undelivered TRANSACTION_COMPLETE" + ); + } + } fn should_sync_wakeup(&self) -> bool { false diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs index 38b90c79c057..edc2613d13b5 100644 --- a/drivers/android/binder/thread.rs +++ b/drivers/android/binder/thread.rs @@ -279,7 +279,7 @@ struct InnerThread { const LOOPER_POLL: u32 = 0x40; impl InnerThread { - fn new() -> Result { + fn new(pid: i32) -> Result { fn next_err_id() -> u32 { static EE_ID: Atomic = Atomic::new(0); EE_ID.fetch_add(1, Relaxed) @@ -290,8 +290,8 @@ fn next_err_id() -> u32 { looper_need_return: false, is_dead: false, process_work_list: false, - reply_work: ThreadError::try_new()?, - return_work: ThreadError::try_new()?, + reply_work: ThreadError::try_new(pid)?, + return_work: ThreadError::try_new(pid)?, work_list: List::new(), current_transaction: None, extended_error: ExtendedError::new(next_err_id(), BR_OK, 0), @@ -445,7 +445,7 @@ impl ListItem<0> for Thread { impl Thread { pub(crate) fn new(id: i32, process: Arc) -> Result> { - let inner = InnerThread::new()?; + let inner = InnerThread::new(process.task.pid())?; Arc::pin_init( try_pin_init!(Thread { @@ -1115,6 +1115,12 @@ fn unwind_transaction_stack(self: &Arc) { let mut inner = thread.inner.lock(); inner.pop_transaction_to_reply(thread.as_ref()) } { + binder_debug!( + DeadTransaction, + "release transaction {} in, still active", + transaction.debug_id + ); + let reply = Err(BR_DEAD_REPLY); if !transaction .from @@ -1305,7 +1311,10 @@ fn transaction_inner(self: &Arc, info: &mut TransactionInfo) -> BinderResu // TODO: We need to ensure that there isn't a pending transaction in the work queue. How // could this happen? let top = self.top_of_transaction_stack()?; - let list_completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?; + let list_completion = DTRWrap::arc_try_new(DeliverCode::new( + BR_TRANSACTION_COMPLETE, + self.process.task.pid(), + ))?; let completion = list_completion.clone_arc(); let transaction = Transaction::new(node_ref, top, self, info)?; @@ -1357,7 +1366,10 @@ fn reply_inner(self: &Arc, info: &mut TransactionInfo) -> BinderResult { // We need to complete the transaction even if we cannot complete building the reply. let out = (|| -> BinderResult<_> { - let completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?; + let completion = DTRWrap::arc_try_new(DeliverCode::new( + BR_TRANSACTION_COMPLETE, + self.process.task.pid(), + ))?; let process = orig.from.process.clone(); let allow_fds = orig.flags & TF_ACCEPT_FDS != 0; let reply = Transaction::new_reply(self, process, info, allow_fds)?; @@ -1397,7 +1409,8 @@ fn oneway_transaction_inner(self: &Arc, info: &mut TransactionInfo) -> Bin } else { BR_TRANSACTION_COMPLETE }; - let list_completion = DTRWrap::arc_try_new(DeliverCode::new(code))?; + let list_completion = + DTRWrap::arc_try_new(DeliverCode::new(code, self.process.task.pid()))?; let completion = list_completion.clone_arc(); self.inner.lock().push_work(list_completion); match transaction.submit(info) { @@ -1653,14 +1666,16 @@ pub(crate) fn release(self: &Arc) { #[pin_data] struct ThreadError { error_code: Atomic, + pid: i32, #[pin] links_track: AtomicTracker, } impl ThreadError { - fn try_new() -> Result> { + fn try_new(pid: i32) -> Result> { DTRWrap::arc_pin_init(pin_init!(Self { error_code: Atomic::new(BR_OK), + pid, links_track <- AtomicTracker::new(), })) .map(ListArc::into_arc) @@ -1687,7 +1702,16 @@ fn do_work( Ok(true) } - fn cancel(self: DArc) {} + fn cancel(self: DArc) { + let code = self.error_code.load(Relaxed); + if code != BR_OK { + binder_debug!( + pid = self.pid, + DeadTransaction, + "undelivered TRANSACTION_ERROR: {code}" + ); + } + } fn should_sync_wakeup(&self) -> bool { false diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs index 069c792d2200..0528070fe700 100644 --- a/drivers/android/binder/transaction.rs +++ b/drivers/android/binder/transaction.rs @@ -488,6 +488,13 @@ fn cancel(self: DArc) { if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 { let reply = Err(BR_DEAD_REPLY); self.from.deliver_reply(reply, &self, None); + } else { + binder_debug!( + pid = self.to.task.pid(), + DeadTransaction, + "undelivered transaction {}, process died", + self.debug_id + ); } self.drop_outstanding_txn();