about summary refs log tree commit diff
path: root/library/std/src/panicking.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/panicking.rs')
-rw-r--r--library/std/src/panicking.rs29
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
             })