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: <core::result::Result<!,E> as std::process::Termination>::report
at /git/rust/library/std/src/process.rs:2164:9
9: <core::result::Result<(),E> 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
.
.
.
.
.
.
.
.
.
.
This commit is contained in:
@@ -2161,7 +2161,9 @@ impl Termination for ! {
|
||||
impl<E: fmt::Debug> Termination for Result<!, E> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user