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.rs18
1 files changed, 17 insertions, 1 deletions
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index e7ce5bc6140..3b02254548b 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -266,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);