fix(core): make sure to signal `ButtonRequest` handler to exit
What changed, and why it matters
This Trezor firmware fix ensures a background task that handles on-device button prompts is properly shut down when a screen layout finishes. Previously, the signal meant to stop that task might not be delivered, leaving the task running. The patch uses a 'replace' flag to guarantee the stop signal is placed in the queue. A stuck button-request task could cause the device and host software to get out of sync, potentially leading to confusing UI states or unexpected behavior during wallet operations.
Treat as a reliability/robustness fix. Review whether the stuck task could be triggered in practice and whether any host-side timeout or retry logic could mask or exploit the desync. No immediate emergency action is indicated by the diff alone, but firmware users should update to a release containing this fix once available.
Security signals we found
Background task lifecycle bug fixed
Possible host-device protocol desync mentioned in comment
UI event queue signal delivery issue
No changelog entry provided
Evidence from the diff
In core/src/trezor/ui/init.py, the Layout class manages a background button_request_task via _handle_button_requests(). When the layout result is ready, the code previously checked if button_request_box was empty and then put(None) to signal the handler to exit. The commit changes this to button_request_box.put(None, replace=True), which replaces any existing value so the signal is always delivered. The commit message states the old behavior could leave button_request_task running because the box value was not replaced with None. The diff also adds a debug log and broadens exception handling around the await is_done block.
Changed components
core/src/trezor/ui/__init__.pyLayout classbutton_request_task / _handle_button_requestsbutton_request_box queueInspect captured patch +4 / −2
diff --git a/core/src/trezor/ui/__init__.py b/core/src/trezor/ui/__init__.py
index 8dd7aa280..4faa4337b 100644
--- a/core/src/trezor/ui/__init__.py
+++ b/core/src/trezor/ui/__init__.py
@@ -262,14 +262,16 @@ class Layout(Generic[T]):
is_done = loop.mailbox()
self.button_request_task = self._handle_button_requests(is_done)
self._start_task(self.button_request_task)
+
result = await self.result_box
if is_done is not None:
# Make sure ButtonRequest is ACKed, before the result is returned.
# Otherwise, THP channel may become desynced (due to two consecutive writes).
+ if __debug__:
+ log.debug(__name__, "waiting for %s", self.button_request_task)
try:
- if self.button_request_box.is_empty():
- self.button_request_box.put(None)
+ self.button_request_box.put(None, replace=True)
await is_done
except Exception as e:
log.exception(__name__, e)
Why this scored 44/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.