fix(core): propagate the exit code from the core app emulator
What changed, and why it matters
This commit fixes how the Trezor emulator exits when running the core app. Previously, the emulator thread did not pass along the actual exit code from the finished task, and it skipped the normal cleanup path. Now it calls the standard `systask_exit()` function with the real exit code. This is a code-correctness fix that mainly affects testing and emulator behavior, not a security vulnerability in the hardware wallet itself.
No immediate security action required. Treat as a normal code-quality fix. If reviewing for release readiness, verify that `systask_exit()` preserves the intended scheduler invariants and that emulator CI tests still pass with correct exit codes.
Security signals we found
Exit-code propagation correctness in emulator/test harness
Removal of duplicated scheduler handoff logic
Use of centralized task exit routine
Evidence from the diff
In core/embed/sys/task/unix/systask.c, the thread_trampoline() function previously called invoke_pushed_fn_call(task) and discarded its return value, then performed an inline cooperative exit by marking the task killed, switching the active task to the kernel task, and signaling its condition variable. The patch captures the return value as exit_code and routes through systask_exit(task, exit_code), which presumably performs the same scheduler handoff plus any additional cleanup or exit-code propagation. The change reduces duplicated logic and ensures the emulator process returns the correct exit status.
Changed components
core/embed/sys/task/unix/systask.cTrezor core emulator (Unix build only)Inspect captured patch +2 / −11
diff --git a/core/embed/sys/task/unix/systask.c b/core/embed/sys/task/unix/systask.c
index b5f84df2..79f545ad 100644
--- a/core/embed/sys/task/unix/systask.c
+++ b/core/embed/sys/task/unix/systask.c
@@ -169,19 +169,10 @@ static void* thread_trampoline(void* arg) {
}
pthread_mutex_unlock(&scheduler->lock);
- invoke_pushed_fn_call(task);
+ int exit_code = (int)invoke_pushed_fn_call(task);
- // Cooperative exit: pick someone else if possible
- pthread_mutex_lock(&scheduler->lock);
- task->killed = true;
-
- // If we're still active, hand off to the kernel thread
- if (scheduler->active_task == task) {
- scheduler->active_task = &scheduler->kernel_task;
- pthread_cond_signal(&scheduler->kernel_task.cv);
- }
+ systask_exit(task, exit_code);
- pthread_mutex_unlock(&scheduler->lock);
return 0;
}
Why this scored 17/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.