From: Jahnavi MN <jahnavimn@google.com>
To: "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Arve Hjønnevåg" <arve@android.com>,
"Todd Kjos" <tkjos@android.com>,
"Christian Brauner" <brauner@kernel.org>,
"Carlos Llamas" <cmllamas@google.com>,
"Alice Ryhl" <aliceryhl@google.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Tamir Duberstein" <tamird@kernel.org>,
"Alexandre Courbot" <acourbot@nvidia.com>,
"Onur Özkan" <work@onurozkan.dev>
Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
Jahnavi MN <jahnavimn@google.com>
Subject: [PATCH v3 7/7] rust_binder: Implement BINDER_DEBUG_DEAD_TRANSACTION
Date: Mon, 13 Jul 2026 12:35:29 +0000 [thread overview]
Message-ID: <20260713-rust_binder_debug_mask-v3-7-0de91bbbbf69@google.com> (raw)
In-Reply-To: <20260713-rust_binder_debug_mask-v3-0-0de91bbbbf69@google.com>
This adds dynamic debug logs for:
- Releasing active transactions during thread stack unwinding.
- Discarded transaction error codes when a thread exits.
- Undelivered transaction acknowledgments (TRANSACTION_COMPLETE)
upon thread exit.
- Undelivered process death and freeze notifications when processes
exit or die.
- Undelivered transactions canceled due to target process death.
We now store the process PID in `ThreadError`, `DeliverCode`, and
`FreezeMessage` to ensure the correct PID is logged on cancellation.
This is necessary because `cancel()` runs from background `kworkers`,
which would otherwise print the wrong PID.
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
drivers/android/binder/freeze.rs | 24 +++++++++++------
drivers/android/binder/node.rs | 9 ++++++-
drivers/android/binder/rust_binder_main.rs | 14 ++++++++--
drivers/android/binder/thread.rs | 42 +++++++++++++++++++++++-------
drivers/android/binder/transaction.rs | 7 +++++
5 files changed, 76 insertions(+), 20 deletions(-)
diff --git a/drivers/android/binder/freeze.rs b/drivers/android/binder/freeze.rs
index 2c99e0995554..7b825ffba557 100644
--- a/drivers/android/binder/freeze.rs
+++ b/drivers/android/binder/freeze.rs
@@ -60,6 +60,7 @@ fn allow_duplicate(&self, node: &DArc<Node>) -> 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<UninitFM, AllocError> {
UniqueArc::new_uninit(flags)
}
- fn init(ua: UninitFM, cookie: FreezeCookie) -> DLArc<FreezeMessage> {
- match ua.pin_init_with(DTRWrap::new(FreezeMessage { cookie })) {
+ fn init(ua: UninitFM, cookie: FreezeCookie, pid: i32) -> DLArc<FreezeMessage> {
+ 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<Self>) {}
+ fn cancel(self: DArc<Self>) {
+ binder_debug!(
+ pid = self.pid,
+ DeadTransaction,
+ "undelivered freeze notification, {:016x}",
+ self.cookie.0
+ );
+ }
fn should_sync_wakeup(&self) -> bool {
false
@@ -251,7 +259,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(())
@@ -272,7 +280,7 @@ pub(crate) fn freeze_notif_done(self: &Arc<Self>, 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 {
@@ -287,7 +295,7 @@ pub(crate) fn freeze_notif_done(self: &Arc<Self>, 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;
}
@@ -340,7 +348,7 @@ pub(crate) fn clear_freeze_notif(self: &Arc<Self>, 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);
@@ -420,7 +428,7 @@ pub(crate) fn prepare_freeze_messages(&self) -> Result<FreezeMessages, AllocErro
continue;
};
let msg_alloc = FreezeMessage::new(GFP_KERNEL)?;
- let msg = FreezeMessage::init(msg_alloc, cookie);
+ let msg = FreezeMessage::init(msg_alloc, cookie, proc.task.pid());
batch.push((proc, msg), GFP_KERNEL)?;
}
diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs
index 87a2e613a816..b9e21b8ec251 100644
--- a/drivers/android/binder/node.rs
+++ b/drivers/android/binder/node.rs
@@ -1120,7 +1120,14 @@ fn do_work(
Ok(cmd != BR_DEAD_BINDER)
}
- fn cancel(self: DArc<Self>) {}
+ fn cancel(self: DArc<Self>) {
+ 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<T>) -> Result<DLArc<T>, kernel::error::Error>
struct DeliverCode {
code: u32,
skip: Atomic<bool>,
+ 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<Self>) {}
+ fn cancel(self: DArc<Self>) {
+ 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 26925d094a59..102413879d1d 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<Self> {
+ fn new(pid: i32) -> Result<Self> {
fn next_err_id() -> u32 {
static EE_ID: Atomic<u32> = 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<Process>) -> Result<Arc<Self>> {
- let inner = InnerThread::new()?;
+ let inner = InnerThread::new(process.task.pid())?;
Arc::pin_init(
try_pin_init!(Thread {
@@ -1108,6 +1108,12 @@ fn unwind_transaction_stack(self: &Arc<Self>) {
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.deliver_single_reply(reply, &transaction) {
break;
@@ -1284,7 +1290,10 @@ fn transaction_inner(self: &Arc<Self>, 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)?;
@@ -1336,7 +1345,10 @@ fn reply_inner(self: &Arc<Self>, 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)?;
@@ -1370,7 +1382,8 @@ fn oneway_transaction_inner(self: &Arc<Self>, 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) {
@@ -1626,14 +1639,16 @@ pub(crate) fn release(self: &Arc<Self>) {
#[pin_data]
struct ThreadError {
error_code: Atomic<u32>,
+ pid: i32,
#[pin]
links_track: AtomicTracker,
}
impl ThreadError {
- fn try_new() -> Result<DArc<Self>> {
+ fn try_new(pid: i32) -> Result<DArc<Self>> {
DTRWrap::arc_pin_init(pin_init!(Self {
error_code: Atomic::new(BR_OK),
+ pid,
links_track <- AtomicTracker::new(),
}))
.map(ListArc::into_arc)
@@ -1660,7 +1675,16 @@ fn do_work(
Ok(true)
}
- fn cancel(self: DArc<Self>) {}
+ fn cancel(self: DArc<Self>) {
+ 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 b56dca55662d..0dbc7a9d16f9 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -489,6 +489,13 @@ fn cancel(self: DArc<Self>) {
if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
let reply = Err(BR_DEAD_REPLY);
self.from.deliver_reply(reply, &self);
+ } else {
+ binder_debug!(
+ pid = self.to.task.pid(),
+ DeadTransaction,
+ "undelivered transaction {}, process died",
+ self.debug_id
+ );
}
self.drop_outstanding_txn();
--
2.55.0.795.g602f6c329a-goog
WARNING: multiple messages have this Message-ID (diff)
From: Jahnavi MN via B4 Relay <devnull+jahnavimn.google.com@kernel.org>
To: "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Arve Hjønnevåg" <arve@android.com>,
"Todd Kjos" <tkjos@android.com>,
"Christian Brauner" <brauner@kernel.org>,
"Carlos Llamas" <cmllamas@google.com>,
"Alice Ryhl" <aliceryhl@google.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Tamir Duberstein" <tamird@kernel.org>,
"Alexandre Courbot" <acourbot@nvidia.com>,
"Onur Özkan" <work@onurozkan.dev>
Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
Jahnavi MN <jahnavimn@google.com>
Subject: [PATCH v3 7/7] rust_binder: Implement BINDER_DEBUG_DEAD_TRANSACTION
Date: Mon, 13 Jul 2026 12:35:29 +0000 [thread overview]
Message-ID: <20260713-rust_binder_debug_mask-v3-7-0de91bbbbf69@google.com> (raw)
In-Reply-To: <20260713-rust_binder_debug_mask-v3-0-0de91bbbbf69@google.com>
From: Jahnavi MN <jahnavimn@google.com>
This adds dynamic debug logs for:
- Releasing active transactions during thread stack unwinding.
- Discarded transaction error codes when a thread exits.
- Undelivered transaction acknowledgments (TRANSACTION_COMPLETE)
upon thread exit.
- Undelivered process death and freeze notifications when processes
exit or die.
- Undelivered transactions canceled due to target process death.
We now store the process PID in `ThreadError`, `DeliverCode`, and
`FreezeMessage` to ensure the correct PID is logged on cancellation.
This is necessary because `cancel()` runs from background `kworkers`,
which would otherwise print the wrong PID.
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
drivers/android/binder/freeze.rs | 24 +++++++++++------
drivers/android/binder/node.rs | 9 ++++++-
drivers/android/binder/rust_binder_main.rs | 14 ++++++++--
drivers/android/binder/thread.rs | 42 +++++++++++++++++++++++-------
drivers/android/binder/transaction.rs | 7 +++++
5 files changed, 76 insertions(+), 20 deletions(-)
diff --git a/drivers/android/binder/freeze.rs b/drivers/android/binder/freeze.rs
index 2c99e0995554..7b825ffba557 100644
--- a/drivers/android/binder/freeze.rs
+++ b/drivers/android/binder/freeze.rs
@@ -60,6 +60,7 @@ fn allow_duplicate(&self, node: &DArc<Node>) -> 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<UninitFM, AllocError> {
UniqueArc::new_uninit(flags)
}
- fn init(ua: UninitFM, cookie: FreezeCookie) -> DLArc<FreezeMessage> {
- match ua.pin_init_with(DTRWrap::new(FreezeMessage { cookie })) {
+ fn init(ua: UninitFM, cookie: FreezeCookie, pid: i32) -> DLArc<FreezeMessage> {
+ 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<Self>) {}
+ fn cancel(self: DArc<Self>) {
+ binder_debug!(
+ pid = self.pid,
+ DeadTransaction,
+ "undelivered freeze notification, {:016x}",
+ self.cookie.0
+ );
+ }
fn should_sync_wakeup(&self) -> bool {
false
@@ -251,7 +259,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(())
@@ -272,7 +280,7 @@ pub(crate) fn freeze_notif_done(self: &Arc<Self>, 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 {
@@ -287,7 +295,7 @@ pub(crate) fn freeze_notif_done(self: &Arc<Self>, 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;
}
@@ -340,7 +348,7 @@ pub(crate) fn clear_freeze_notif(self: &Arc<Self>, 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);
@@ -420,7 +428,7 @@ pub(crate) fn prepare_freeze_messages(&self) -> Result<FreezeMessages, AllocErro
continue;
};
let msg_alloc = FreezeMessage::new(GFP_KERNEL)?;
- let msg = FreezeMessage::init(msg_alloc, cookie);
+ let msg = FreezeMessage::init(msg_alloc, cookie, proc.task.pid());
batch.push((proc, msg), GFP_KERNEL)?;
}
diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs
index 87a2e613a816..b9e21b8ec251 100644
--- a/drivers/android/binder/node.rs
+++ b/drivers/android/binder/node.rs
@@ -1120,7 +1120,14 @@ fn do_work(
Ok(cmd != BR_DEAD_BINDER)
}
- fn cancel(self: DArc<Self>) {}
+ fn cancel(self: DArc<Self>) {
+ 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<T>) -> Result<DLArc<T>, kernel::error::Error>
struct DeliverCode {
code: u32,
skip: Atomic<bool>,
+ 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<Self>) {}
+ fn cancel(self: DArc<Self>) {
+ 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 26925d094a59..102413879d1d 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<Self> {
+ fn new(pid: i32) -> Result<Self> {
fn next_err_id() -> u32 {
static EE_ID: Atomic<u32> = 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<Process>) -> Result<Arc<Self>> {
- let inner = InnerThread::new()?;
+ let inner = InnerThread::new(process.task.pid())?;
Arc::pin_init(
try_pin_init!(Thread {
@@ -1108,6 +1108,12 @@ fn unwind_transaction_stack(self: &Arc<Self>) {
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.deliver_single_reply(reply, &transaction) {
break;
@@ -1284,7 +1290,10 @@ fn transaction_inner(self: &Arc<Self>, 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)?;
@@ -1336,7 +1345,10 @@ fn reply_inner(self: &Arc<Self>, 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)?;
@@ -1370,7 +1382,8 @@ fn oneway_transaction_inner(self: &Arc<Self>, 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) {
@@ -1626,14 +1639,16 @@ pub(crate) fn release(self: &Arc<Self>) {
#[pin_data]
struct ThreadError {
error_code: Atomic<u32>,
+ pid: i32,
#[pin]
links_track: AtomicTracker,
}
impl ThreadError {
- fn try_new() -> Result<DArc<Self>> {
+ fn try_new(pid: i32) -> Result<DArc<Self>> {
DTRWrap::arc_pin_init(pin_init!(Self {
error_code: Atomic::new(BR_OK),
+ pid,
links_track <- AtomicTracker::new(),
}))
.map(ListArc::into_arc)
@@ -1660,7 +1675,16 @@ fn do_work(
Ok(true)
}
- fn cancel(self: DArc<Self>) {}
+ fn cancel(self: DArc<Self>) {
+ 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 b56dca55662d..0dbc7a9d16f9 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -489,6 +489,13 @@ fn cancel(self: DArc<Self>) {
if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
let reply = Err(BR_DEAD_REPLY);
self.from.deliver_reply(reply, &self);
+ } else {
+ binder_debug!(
+ pid = self.to.task.pid(),
+ DeadTransaction,
+ "undelivered transaction {}, process died",
+ self.debug_id
+ );
}
self.drop_outstanding_txn();
--
2.55.0.795.g602f6c329a-goog
next prev parent reply other threads:[~2026-07-13 12:35 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-13 12:35 [PATCH v3 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN
2026-07-13 12:35 ` Jahnavi MN via B4 Relay
2026-07-13 12:35 ` [PATCH v3 1/7] rust_binder: Add " Jahnavi MN
2026-07-13 12:35 ` Jahnavi MN via B4 Relay
2026-07-13 12:35 ` [PATCH v3 2/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for freezer-related operation Jahnavi MN
2026-07-13 12:35 ` Jahnavi MN via B4 Relay
2026-07-13 12:35 ` [PATCH v3 3/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for refcounting and death notifications Jahnavi MN
2026-07-13 12:35 ` Jahnavi MN via B4 Relay
2026-07-13 12:35 ` [PATCH v3 4/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for transaction parsing failures Jahnavi MN
2026-07-13 12:35 ` Jahnavi MN via B4 Relay
2026-07-13 12:35 ` [PATCH v3 5/7] rust_binder: Implement BINDER_DEBUG_FAILED_TRANSACTION Jahnavi MN
2026-07-13 12:35 ` Jahnavi MN via B4 Relay
2026-07-13 12:35 ` [PATCH v3 6/7] rust_binder: Implement BINDER_DEBUG_DEATH_NOTIFICATION Jahnavi MN
2026-07-13 12:35 ` Jahnavi MN via B4 Relay
2026-07-13 12:35 ` Jahnavi MN [this message]
2026-07-13 12:35 ` [PATCH v3 7/7] rust_binder: Implement BINDER_DEBUG_DEAD_TRANSACTION Jahnavi MN via B4 Relay
2026-07-13 21:04 ` Carlos Llamas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260713-rust_binder_debug_mask-v3-7-0de91bbbbf69@google.com \
--to=jahnavimn@google.com \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=aliceryhl@google.com \
--cc=arve@android.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=brauner@kernel.org \
--cc=cmllamas@google.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tamird@kernel.org \
--cc=tkjos@android.com \
--cc=tmgross@umich.edu \
--cc=work@onurozkan.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.