Skip to content

Commit 42f5828

Browse files
committed
Auto merge of rust-lang#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 rust-lang#115610
2 parents 0692db1 + b594807 commit 42f5828

File tree

4 files changed

+63
-60
lines changed

4 files changed

+63
-60
lines changed

compiler/rustc_driver_impl/src/lib.rs

+54-26
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
88
#![feature(lazy_cell)]
99
#![feature(decl_macro)]
10-
#![feature(ice_to_disk)]
10+
#![feature(panic_update_hook)]
1111
#![feature(let_chains)]
1212
#![recursion_limit = "256"]
1313
#![allow(rustc::potential_query_instability)]
@@ -50,9 +50,9 @@ use std::collections::BTreeMap;
5050
use std::env;
5151
use std::ffi::OsString;
5252
use std::fmt::Write as _;
53-
use std::fs;
53+
use std::fs::{self, File};
5454
use std::io::{self, IsTerminal, Read, Write};
55-
use std::panic::{self, catch_unwind};
55+
use std::panic::{self, catch_unwind, PanicInfo};
5656
use std::path::PathBuf;
5757
use std::process::{self, Command, Stdio};
5858
use std::str;
@@ -1326,31 +1326,59 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
13261326
std::env::set_var("RUST_BACKTRACE", "full");
13271327
}
13281328

1329-
panic::set_hook(Box::new(move |info| {
1330-
// If the error was caused by a broken pipe then this is not a bug.
1331-
// Write the error and return immediately. See #98700.
1332-
#[cfg(windows)]
1333-
if let Some(msg) = info.payload().downcast_ref::<String>() {
1334-
if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") {
1335-
// the error code is already going to be reported when the panic unwinds up the stack
1336-
let handler = EarlyErrorHandler::new(ErrorOutputType::default());
1337-
let _ = handler.early_error_no_abort(msg.clone());
1338-
return;
1339-
}
1340-
};
1341-
1342-
// Invoke the default handler, which prints the actual panic message and optionally a backtrace
1343-
// Don't do this for delayed bugs, which already emit their own more useful backtrace.
1344-
if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
1345-
std::panic_hook_with_disk_dump(info, ice_path().as_deref());
1329+
panic::update_hook(Box::new(
1330+
move |default_hook: &(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static),
1331+
info: &PanicInfo<'_>| {
1332+
// If the error was caused by a broken pipe then this is not a bug.
1333+
// Write the error and return immediately. See #98700.
1334+
#[cfg(windows)]
1335+
if let Some(msg) = info.payload().downcast_ref::<String>() {
1336+
if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)")
1337+
{
1338+
// the error code is already going to be reported when the panic unwinds up the stack
1339+
let handler = EarlyErrorHandler::new(ErrorOutputType::default());
1340+
let _ = handler.early_error_no_abort(msg.clone());
1341+
return;
1342+
}
1343+
};
13461344

1347-
// Separate the output with an empty line
1348-
eprintln!();
1349-
}
1345+
// Invoke the default handler, which prints the actual panic message and optionally a backtrace
1346+
// Don't do this for delayed bugs, which already emit their own more useful backtrace.
1347+
if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
1348+
default_hook(info);
1349+
// Separate the output with an empty line
1350+
eprintln!();
1351+
1352+
if let Some(ice_path) = ice_path()
1353+
&& let Ok(mut out) =
1354+
File::options().create(true).append(true).open(&ice_path)
1355+
{
1356+
// The current implementation always returns `Some`.
1357+
let location = info.location().unwrap();
1358+
let msg = match info.payload().downcast_ref::<&'static str>() {
1359+
Some(s) => *s,
1360+
None => match info.payload().downcast_ref::<String>() {
1361+
Some(s) => &s[..],
1362+
None => "Box<dyn Any>",
1363+
},
1364+
};
1365+
let thread = std::thread::current();
1366+
let name = thread.name().unwrap_or("<unnamed>");
1367+
let _ = write!(
1368+
&mut out,
1369+
"thread '{name}' panicked at {location}:\n\
1370+
{msg}\n\
1371+
stack backtrace:\n\
1372+
{:#}",
1373+
std::backtrace::Backtrace::force_capture()
1374+
);
1375+
}
1376+
}
13501377

1351-
// Print the ICE message
1352-
report_ice(info, bug_report_url, extra_info);
1353-
}));
1378+
// Print the ICE message
1379+
report_ice(info, bug_report_url, extra_info);
1380+
},
1381+
));
13541382
}
13551383

13561384
/// Prints the ICE message, including query stack, but without backtrace.

library/std/src/lib.rs

-3
Original file line numberDiff line numberDiff line change
@@ -637,9 +637,6 @@ pub mod alloc;
637637
// Private support modules
638638
mod panicking;
639639

640-
#[unstable(feature = "ice_to_disk", issue = "none")]
641-
pub use panicking::panic_hook_with_disk_dump;
642-
643640
#[path = "../../backtrace/src/lib.rs"]
644641
#[allow(dead_code, unused_attributes, fuzzy_provenance_casts)]
645642
mod backtrace_rs;

library/std/src/panicking.rs

+7-29
Original file line numberDiff line numberDiff line change
@@ -236,14 +236,6 @@ where
236236

237237
/// The default panic handler.
238238
fn default_hook(info: &PanicInfo<'_>) {
239-
panic_hook_with_disk_dump(info, None)
240-
}
241-
242-
#[unstable(feature = "ice_to_disk", issue = "none")]
243-
/// The implementation of the default panic handler.
244-
///
245-
/// It can also write the backtrace to a given `path`. This functionality is used only by `rustc`.
246-
pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path::Path>) {
247239
// If this is a double panic, make sure that we print a backtrace
248240
// for this panic. Otherwise only print it if logging is enabled.
249241
let backtrace = if info.force_no_backtrace() {
@@ -267,7 +259,7 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path
267259
let thread = thread_info::current_thread();
268260
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
269261

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

273265
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
@@ -281,37 +273,23 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path
281273
}
282274
Some(BacktraceStyle::Off) => {
283275
if FIRST_PANIC.swap(false, Ordering::SeqCst) {
284-
if let Some(path) = path {
285-
let _ = writeln!(
286-
err,
287-
"note: a backtrace for this error was stored at `{}`",
288-
path.display(),
289-
);
290-
} else {
291-
let _ = writeln!(
292-
err,
293-
"note: run with `RUST_BACKTRACE=1` environment variable to display a \
276+
let _ = writeln!(
277+
err,
278+
"note: run with `RUST_BACKTRACE=1` environment variable to display a \
294279
backtrace"
295-
);
296-
}
280+
);
297281
}
298282
}
299283
// If backtraces aren't supported or are forced-off, do nothing.
300284
None => {}
301285
}
302286
};
303287

304-
if let Some(path) = path
305-
&& let Ok(mut out) = crate::fs::File::options().create(true).append(true).open(&path)
306-
{
307-
write(&mut out, BacktraceStyle::full());
308-
}
309-
310288
if let Some(local) = set_output_capture(None) {
311-
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()), backtrace);
289+
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()));
312290
set_output_capture(Some(local));
313291
} else if let Some(mut out) = panic_output() {
314-
write(&mut out, backtrace);
292+
write(&mut out);
315293
}
316294
}
317295

tests/run-make/dump-ice-to-disk/check.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ rm $TMPDIR/rustc-ice-*.txt
2222
# Explicitly disabling ICE dump
2323
export RUSTC_ICE=0
2424
$RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-disabled.log 2>&1
25-
should_be_empty_tmp=$(ls -l $TMPDIR/rustc-ice-*.txt | wc -l)
26-
should_be_empty_dot=$(ls -l ./rustc-ice-*.txt | wc -l)
25+
should_be_empty_tmp=$(ls -l $TMPDIR/rustc-ice-*.txt 2>/dev/null | wc -l)
26+
should_be_empty_dot=$(ls -l ./rustc-ice-*.txt 2>/dev/null | wc -l)
2727

2828
echo "#### ICE Dump content:"
2929
echo $content

0 commit comments

Comments
 (0)