Skip to content

Commit

Permalink
On nightly, dump ICE backtraces to disk
Browse files Browse the repository at this point in the history
Implement rust-lang/compiler-team#578.

When an ICE is encountered on nightly releases, the new rustc panic
handler will also write the contents of the backtrace to disk. If any
`delay_span_bug`s are encountered, their backtrace is also added to the
file. The platform and rustc version will also be collected.
  • Loading branch information
estebank committed Jul 19, 2023
1 parent 31f90f7 commit b9eb2be
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 7 deletions.
3 changes: 3 additions & 0 deletions std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,9 @@ pub mod alloc;
// Private support modules
mod panicking;

#[unstable(feature = "ice_to_disk", issue = "none")]
pub use panicking::panic_hook_with_disk_dump;

#[path = "../../backtrace/src/lib.rs"]
#[allow(dead_code, unused_attributes, fuzzy_provenance_casts)]
mod backtrace_rs;
Expand Down
38 changes: 31 additions & 7 deletions std/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,16 @@ where
*hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info)));
}

/// The default panic handler.
fn default_hook(info: &PanicInfo<'_>) {
panic_hook_with_disk_dump(info, None)
}

#[unstable(feature = "ice_to_disk", issue = "none")]
/// The implementation of the default panic handler.
///
/// It can also write the backtrace to a given `path`. This functionality is used only by `rustc`.
pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path::Path>) {
// If this is a double panic, make sure that we print a backtrace
// for this panic. Otherwise only print it if logging is enabled.
let backtrace = if panic_count::get_count() >= 2 {
Expand All @@ -256,7 +265,7 @@ fn default_hook(info: &PanicInfo<'_>) {
let thread = thread_info::current_thread();
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");

let write = |err: &mut dyn crate::io::Write| {
let write = |err: &mut dyn crate::io::Write, backtrace: Option<BacktraceStyle>| {
let _ = writeln!(err, "thread '{name}' panicked at '{msg}', {location}");

static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
Expand All @@ -270,22 +279,37 @@ fn default_hook(info: &PanicInfo<'_>) {
}
Some(BacktraceStyle::Off) => {
if FIRST_PANIC.swap(false, Ordering::SeqCst) {
let _ = writeln!(
err,
"note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace"
);
if let Some(path) = path {
let _ = writeln!(
err,
"note: a backtrace for this error was stored at `{}`",
path.display(),
);
} else {
let _ = writeln!(
err,
"note: run with `RUST_BACKTRACE=1` environment variable to display a \
backtrace"
);
}
}
}
// If backtraces aren't supported, do nothing.
None => {}
}
};

if let Some(path) = path
&& let Ok(mut out) = crate::fs::File::options().create(true).write(true).open(&path)
{
write(&mut out, BacktraceStyle::full());
}

if let Some(local) = set_output_capture(None) {
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()));
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()), backtrace);
set_output_capture(Some(local));
} else if let Some(mut out) = panic_output() {
write(&mut out);
write(&mut out, backtrace);
}
}

Expand Down

0 comments on commit b9eb2be

Please sign in to comment.