about summary refs log tree commit diff
path: root/compiler/rustc_query_system/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-07-20 01:29:17 +0000
committerbors <bors@rust-lang.org>2023-07-20 01:29:17 +0000
commita6cdd81eff52566542cecdc1ce381dbe42cf77fb (patch)
treed8c79736ebadbccb2caf9477add711b55a7c6151 /compiler/rustc_query_system/src
parent39f42ad9e8430a8abb06c262346e89593278c515 (diff)
parent217d97adb85d072c3d567cd8801021d3dc96223c (diff)
downloadrust-a6cdd81eff52566542cecdc1ce381dbe42cf77fb.tar.gz
rust-a6cdd81eff52566542cecdc1ce381dbe42cf77fb.zip
Auto merge of #108714 - estebank:ice_dump, r=oli-obk
On nightly, dump ICE backtraces to disk

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.

<img width="1032" alt="Screenshot 2023-03-03 at 2 13 25 PM" src="https://user-images.githubusercontent.com/1606434/222842420-8e039740-4042-4563-b31d-599677171acf.png">

The current behavior will *always* write to disk on nightly builds, regardless of whether the backtrace is printed to the terminal, unless the environment variable `RUSTC_ICE_DISK_DUMP` is set to `0`. This is a compromise and can be changed.
Diffstat (limited to 'compiler/rustc_query_system/src')
-rw-r--r--compiler/rustc_query_system/src/query/job.rs45
1 files changed, 33 insertions, 12 deletions
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index f45f7ca5da6..e964ba851bd 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -13,6 +13,7 @@ use rustc_session::Session;
 use rustc_span::Span;
 
 use std::hash::Hash;
+use std::io::Write;
 use std::num::NonZeroU64;
 
 #[cfg(parallel_compiler)]
@@ -617,30 +618,50 @@ pub fn print_query_stack<Qcx: QueryContext>(
     mut current_query: Option<QueryJobId>,
     handler: &Handler,
     num_frames: Option<usize>,
+    mut file: Option<std::fs::File>,
 ) -> usize {
     // Be careful relying on global state here: this code is called from
     // a panic hook, which means that the global `Handler` may be in a weird
     // state if it was responsible for triggering the panic.
-    let mut i = 0;
+    let mut count_printed = 0;
+    let mut count_total = 0;
     let query_map = qcx.try_collect_active_jobs();
 
+    if let Some(ref mut file) = file {
+        let _ = writeln!(file, "\n\nquery stack during panic:");
+    }
     while let Some(query) = current_query {
-        if Some(i) == num_frames {
-            break;
-        }
         let Some(query_info) = query_map.as_ref().and_then(|map| map.get(&query)) else {
             break;
         };
-        let mut diag = Diagnostic::new(
-            Level::FailureNote,
-            format!("#{} [{:?}] {}", i, query_info.query.dep_kind, query_info.query.description),
-        );
-        diag.span = query_info.job.span.into();
-        handler.force_print_diagnostic(diag);
+        if Some(count_printed) < num_frames || num_frames.is_none() {
+            // Only print to stderr as many stack frames as `num_frames` when present.
+            let mut diag = Diagnostic::new(
+                Level::FailureNote,
+                format!(
+                    "#{} [{:?}] {}",
+                    count_printed, query_info.query.dep_kind, query_info.query.description
+                ),
+            );
+            diag.span = query_info.job.span.into();
+            handler.force_print_diagnostic(diag);
+            count_printed += 1;
+        }
+
+        if let Some(ref mut file) = file {
+            let _ = writeln!(
+                file,
+                "#{} [{:?}] {}",
+                count_total, query_info.query.dep_kind, query_info.query.description
+            );
+        }
 
         current_query = query_info.job.parent;
-        i += 1;
+        count_total += 1;
     }
 
-    i
+    if let Some(ref mut file) = file {
+        let _ = writeln!(file, "end of query stack");
+    }
+    count_printed
 }