From 563aa12a22a53d277bfb49083c1a4fe0b8b8286c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 10 Jun 2022 13:37:52 -0700 Subject: [PATCH] Do not panic in Termination impl on closed stderr Repro: #![feature(backtrace)] use std::backtrace::Backtrace; use std::io::{self, Write as _}; use std::panic::{self, PanicInfo}; #[derive(Debug)] pub struct Error; fn panic_hook(panic_info: &PanicInfo) { let backtrace = Backtrace::force_capture(); let _ = write!(io::stdout(), "{}\n{}", panic_info, backtrace); } fn main() -> Result<(), Error> { panic::set_hook(Box::new(panic_hook)); let stderr = io::stderr(); let mut stderr = stderr.lock(); while stderr.write_all(b".\n").is_ok() {} Err(Error) } Before: $ RUST_BACKTRACE=1 target/debug/testing 3>&2 2>&1 1>&3 | head . . . . . . . . . . panicked at 'failed printing to stderr: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9 0: testing::panic_hook at ./src/main.rs:11:21 1: core::ops::function::Fn::call at /git/rust/library/core/src/ops/function.rs:77:5 2: std::panicking::rust_panic_with_hook 3: std::panicking::begin_panic_handler::{{closure}} 4: std::sys_common::backtrace::__rust_end_short_backtrace 5: rust_begin_unwind 6: core::panicking::panic_fmt 7: std::io::stdio::_eprint 8: as std::process::Termination>::report at /git/rust/library/std/src/process.rs:2164:9 9: as std::process::Termination>::report at /git/rust/library/std/src/process.rs:2148:25 10: std::rt::lang_start::{{closure}} at /git/rust/library/std/src/rt.rs:145:18 11: std::rt::lang_start_internal 12: std::rt::lang_start at /git/rust/library/std/src/rt.rs:144:17 13: main 14: __libc_start_main at /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16 15: _start After: $ RUST_BACKTRACE=1 target/debug/testing 3>&2 2>&1 1>&3 | head . . . . . . . . . . --- library/std/src/process.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 1def9fe0972..c9595a96567 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2161,7 +2161,9 @@ fn report(self) -> ExitCode { impl Termination for Result { fn report(self) -> ExitCode { let Err(err) = self; - eprintln!("Error: {err:?}"); + // Ignore error if the write fails, for example because stderr is + // already closed. There is not much point panicking at this point. + let _ = writeln!(io::stderr(), "Error: {err:?}"); ExitCode::FAILURE } } -- GitLab