diff options
Diffstat (limited to 'library/std/src/panicking.rs')
| -rw-r--r-- | library/std/src/panicking.rs | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 97f800dddaa..3b02254548b 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -81,7 +81,9 @@ extern "C" fn __rust_foreign_exception() -> ! { rtabort!("Rust cannot catch foreign exceptions"); } +#[derive(Default)] enum Hook { + #[default] Default, Custom(Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send>), } @@ -96,13 +98,6 @@ impl Hook { } } -impl Default for Hook { - #[inline] - fn default() -> Hook { - Hook::Default - } -} - static HOOK: RwLock<Hook> = RwLock::new(Hook::Default); /// Registers a custom panic hook, replacing the previously registered hook. @@ -271,7 +266,23 @@ fn default_hook(info: &PanicHookInfo<'_>) { // Use a lock to prevent mixed output in multithreading context. // Some platforms also require it when printing a backtrace, like `SymFromAddr` on Windows. let mut lock = backtrace::lock(); - let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}"); + // Try to write the panic message to a buffer first to prevent other concurrent outputs + // interleaving with it. + let mut buffer = [0u8; 512]; + let mut cursor = crate::io::Cursor::new(&mut buffer[..]); + + let write_msg = |dst: &mut dyn crate::io::Write| { + // We add a newline to ensure the panic message appears at the start of a line. + writeln!(dst, "\nthread '{name}' panicked at {location}:\n{msg}") + }; + + if write_msg(&mut cursor).is_ok() { + let pos = cursor.position() as usize; + let _ = err.write_all(&buffer[0..pos]); + } else { + // The message did not fit into the buffer, write it directly instead. + let _ = write_msg(err); + }; static FIRST_PANIC: AtomicBool = AtomicBool::new(true); @@ -623,7 +634,7 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { // Lazily, the first time this gets called, run the actual string formatting. self.string.get_or_insert_with(|| { let mut s = String::new(); - let mut fmt = fmt::Formatter::new(&mut s); + let mut fmt = fmt::Formatter::new(&mut s, fmt::FormattingOptions::new()); let _err = fmt::Display::fmt(&inner, &mut fmt); s }) |
