Skip to content

Commit 658fd54

Browse files
molofskyanthonyshewclaude
authored
fix: don't use eprintln! in the panic hook (#13637)
### Problem `panic_handler` ends with `eprintln!`, which **panics if the write to stderr fails**. A panic raised inside a panic hook aborts the process immediately, so the hook never completes and the crash report it exists to print is lost. The user sees a bare `Aborted (core dumped)` with no diagnostics at all. This is reachable in practice during TUI teardown, where the terminal fd can already be gone. Observed on 2.10.1 with a locally symbolized build: ``` turborepo_ui::tui::app::cleanup crates/turborepo-ui/src/tui/app.rs:1111 -> ratatui Terminal::drop ratatui-core/src/terminal/terminal.rs:119 eprintln!("Failed to show the cursor") -> write fails -> panic -> turborepo_lib::panic_handler crates/turborepo-lib/src/panic_handler.rs:66 eprintln! -> write fails -> panic -> double panic -> abort() (SIGABRT) ``` ratatui's `Drop` reports a failed `show_cursor` via `eprintln!`; that write fails too and panics; the hook then panics the same way, and the second panic aborts. The first panic is ratatui's to own — but the hook shouldn't be capable of turning *any* panic into an abort. ### Fix Write to stderr directly and discard the error: ```rust let _ = std::io::stderr().write_all( format!("Oops! Turbo has crashed.\n\n{report_message}\n").as_bytes(), ); ``` A panic hook runs precisely when things are already broken, so it shouldn't assume its own output path works. If stderr is unusable we now print nothing, instead of escalating to an abort. When stderr *is* usable — the overwhelmingly common case — behaviour is unchanged. ### Notes / testing - Applies to `main`; `eprintln!` is the only panicking macro in the hook. - The equivalent change was built and exercised on 2.10.1 (Linux, musl target): the double-panic abort stopped reproducing. - The changed code compiles standalone under `-D warnings` (no unused import, no type error). - **I have not built the full workspace against `main`** — I don't have `capnp`/`zig` and the pinned nightly on this machine. Happy for CI to be the judge, which is why this is a draft. Filed as a draft for maintainer review; glad to adjust the wording or add a regression test if useful. --------- Co-authored-by: Anthony Shew <anthonyshew@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent a936402 commit 658fd54

1 file changed

Lines changed: 6 additions & 5 deletions

File tree

crates/turborepo-lib/src/panic_handler.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::io::Write;
2+
13
use human_panic::report::{Method, Report};
24

35
use crate::get_version;
@@ -63,11 +65,10 @@ pub fn panic_handler(panic_info: &std::panic::PanicHookInfo) {
6365
)
6466
};
6567

66-
eprintln!(
67-
"Oops! Turbo has crashed.
68-
69-
{report_message}"
70-
);
68+
// `eprintln!` panics if stderr is unwritable, and a panic in a panic hook
69+
// aborts.
70+
let _ = std::io::stderr()
71+
.write_all(format!("Oops! Turbo has crashed.\n\n{report_message}\n").as_bytes());
7172
}
7273

7374
#[cfg(test)]

0 commit comments

Comments
 (0)