Auto merge of #115627 - compiler-errors:icedump-no-std, r=m-ou-se
Don't modify libstd to dump rustc ICEs Do a much simpler thing and just dump a `std::backtrace::Backtrace` to file. r? `@estebank` `@oli-obk` Fixes #115610
This commit is contained in:
commit
42f5828b01
4 changed files with 63 additions and 60 deletions
|
@ -7,7 +7,7 @@
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
#![feature(lazy_cell)]
|
#![feature(lazy_cell)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
#![feature(ice_to_disk)]
|
#![feature(panic_update_hook)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![allow(rustc::potential_query_instability)]
|
#![allow(rustc::potential_query_instability)]
|
||||||
|
@ -50,9 +50,9 @@ use std::collections::BTreeMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::fmt::Write as _;
|
use std::fmt::Write as _;
|
||||||
use std::fs;
|
use std::fs::{self, File};
|
||||||
use std::io::{self, IsTerminal, Read, Write};
|
use std::io::{self, IsTerminal, Read, Write};
|
||||||
use std::panic::{self, catch_unwind};
|
use std::panic::{self, catch_unwind, PanicInfo};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::{self, Command, Stdio};
|
use std::process::{self, Command, Stdio};
|
||||||
use std::str;
|
use std::str;
|
||||||
|
@ -1326,31 +1326,59 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
|
||||||
std::env::set_var("RUST_BACKTRACE", "full");
|
std::env::set_var("RUST_BACKTRACE", "full");
|
||||||
}
|
}
|
||||||
|
|
||||||
panic::set_hook(Box::new(move |info| {
|
panic::update_hook(Box::new(
|
||||||
// If the error was caused by a broken pipe then this is not a bug.
|
move |default_hook: &(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static),
|
||||||
// Write the error and return immediately. See #98700.
|
info: &PanicInfo<'_>| {
|
||||||
#[cfg(windows)]
|
// If the error was caused by a broken pipe then this is not a bug.
|
||||||
if let Some(msg) = info.payload().downcast_ref::<String>() {
|
// Write the error and return immediately. See #98700.
|
||||||
if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") {
|
#[cfg(windows)]
|
||||||
// the error code is already going to be reported when the panic unwinds up the stack
|
if let Some(msg) = info.payload().downcast_ref::<String>() {
|
||||||
let handler = EarlyErrorHandler::new(ErrorOutputType::default());
|
if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)")
|
||||||
let _ = handler.early_error_no_abort(msg.clone());
|
{
|
||||||
return;
|
// the error code is already going to be reported when the panic unwinds up the stack
|
||||||
|
let handler = EarlyErrorHandler::new(ErrorOutputType::default());
|
||||||
|
let _ = handler.early_error_no_abort(msg.clone());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invoke the default handler, which prints the actual panic message and optionally a backtrace
|
||||||
|
// Don't do this for delayed bugs, which already emit their own more useful backtrace.
|
||||||
|
if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
|
||||||
|
default_hook(info);
|
||||||
|
// Separate the output with an empty line
|
||||||
|
eprintln!();
|
||||||
|
|
||||||
|
if let Some(ice_path) = ice_path()
|
||||||
|
&& let Ok(mut out) =
|
||||||
|
File::options().create(true).append(true).open(&ice_path)
|
||||||
|
{
|
||||||
|
// The current implementation always returns `Some`.
|
||||||
|
let location = info.location().unwrap();
|
||||||
|
let msg = match info.payload().downcast_ref::<&'static str>() {
|
||||||
|
Some(s) => *s,
|
||||||
|
None => match info.payload().downcast_ref::<String>() {
|
||||||
|
Some(s) => &s[..],
|
||||||
|
None => "Box<dyn Any>",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let thread = std::thread::current();
|
||||||
|
let name = thread.name().unwrap_or("<unnamed>");
|
||||||
|
let _ = write!(
|
||||||
|
&mut out,
|
||||||
|
"thread '{name}' panicked at {location}:\n\
|
||||||
|
{msg}\n\
|
||||||
|
stack backtrace:\n\
|
||||||
|
{:#}",
|
||||||
|
std::backtrace::Backtrace::force_capture()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Invoke the default handler, which prints the actual panic message and optionally a backtrace
|
// Print the ICE message
|
||||||
// Don't do this for delayed bugs, which already emit their own more useful backtrace.
|
report_ice(info, bug_report_url, extra_info);
|
||||||
if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
|
},
|
||||||
std::panic_hook_with_disk_dump(info, ice_path().as_deref());
|
));
|
||||||
|
|
||||||
// Separate the output with an empty line
|
|
||||||
eprintln!();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print the ICE message
|
|
||||||
report_ice(info, bug_report_url, extra_info);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints the ICE message, including query stack, but without backtrace.
|
/// Prints the ICE message, including query stack, but without backtrace.
|
||||||
|
|
|
@ -637,9 +637,6 @@ pub mod alloc;
|
||||||
// Private support modules
|
// Private support modules
|
||||||
mod panicking;
|
mod panicking;
|
||||||
|
|
||||||
#[unstable(feature = "ice_to_disk", issue = "none")]
|
|
||||||
pub use panicking::panic_hook_with_disk_dump;
|
|
||||||
|
|
||||||
#[path = "../../backtrace/src/lib.rs"]
|
#[path = "../../backtrace/src/lib.rs"]
|
||||||
#[allow(dead_code, unused_attributes, fuzzy_provenance_casts)]
|
#[allow(dead_code, unused_attributes, fuzzy_provenance_casts)]
|
||||||
mod backtrace_rs;
|
mod backtrace_rs;
|
||||||
|
|
|
@ -236,14 +236,6 @@ where
|
||||||
|
|
||||||
/// The default panic handler.
|
/// The default panic handler.
|
||||||
fn default_hook(info: &PanicInfo<'_>) {
|
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
|
// If this is a double panic, make sure that we print a backtrace
|
||||||
// for this panic. Otherwise only print it if logging is enabled.
|
// for this panic. Otherwise only print it if logging is enabled.
|
||||||
let backtrace = if info.force_no_backtrace() {
|
let backtrace = if info.force_no_backtrace() {
|
||||||
|
@ -267,7 +259,7 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path
|
||||||
let thread = thread_info::current_thread();
|
let thread = thread_info::current_thread();
|
||||||
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
|
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
|
||||||
|
|
||||||
let write = |err: &mut dyn crate::io::Write, backtrace: Option<BacktraceStyle>| {
|
let write = |err: &mut dyn crate::io::Write| {
|
||||||
let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}");
|
let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}");
|
||||||
|
|
||||||
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
|
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
|
||||||
|
@ -281,19 +273,11 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path
|
||||||
}
|
}
|
||||||
Some(BacktraceStyle::Off) => {
|
Some(BacktraceStyle::Off) => {
|
||||||
if FIRST_PANIC.swap(false, Ordering::SeqCst) {
|
if FIRST_PANIC.swap(false, Ordering::SeqCst) {
|
||||||
if let Some(path) = path {
|
let _ = writeln!(
|
||||||
let _ = writeln!(
|
err,
|
||||||
err,
|
"note: run with `RUST_BACKTRACE=1` environment variable to display a \
|
||||||
"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"
|
backtrace"
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If backtraces aren't supported or are forced-off, do nothing.
|
// If backtraces aren't supported or are forced-off, do nothing.
|
||||||
|
@ -301,17 +285,11 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(path) = path
|
|
||||||
&& let Ok(mut out) = crate::fs::File::options().create(true).append(true).open(&path)
|
|
||||||
{
|
|
||||||
write(&mut out, BacktraceStyle::full());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(local) = set_output_capture(None) {
|
if let Some(local) = set_output_capture(None) {
|
||||||
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()), backtrace);
|
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()));
|
||||||
set_output_capture(Some(local));
|
set_output_capture(Some(local));
|
||||||
} else if let Some(mut out) = panic_output() {
|
} else if let Some(mut out) = panic_output() {
|
||||||
write(&mut out, backtrace);
|
write(&mut out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ rm $TMPDIR/rustc-ice-*.txt
|
||||||
# Explicitly disabling ICE dump
|
# Explicitly disabling ICE dump
|
||||||
export RUSTC_ICE=0
|
export RUSTC_ICE=0
|
||||||
$RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-disabled.log 2>&1
|
$RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-disabled.log 2>&1
|
||||||
should_be_empty_tmp=$(ls -l $TMPDIR/rustc-ice-*.txt | wc -l)
|
should_be_empty_tmp=$(ls -l $TMPDIR/rustc-ice-*.txt 2>/dev/null | wc -l)
|
||||||
should_be_empty_dot=$(ls -l ./rustc-ice-*.txt | wc -l)
|
should_be_empty_dot=$(ls -l ./rustc-ice-*.txt 2>/dev/null | wc -l)
|
||||||
|
|
||||||
echo "#### ICE Dump content:"
|
echo "#### ICE Dump content:"
|
||||||
echo $content
|
echo $content
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue