Skip to content

Commit

Permalink
Print a backtrace in const eval if interrupted
Browse files Browse the repository at this point in the history
  • Loading branch information
saethlin committed May 25, 2023
1 parent eb9da7b commit 38a5fee
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 7 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3413,6 +3413,7 @@ dependencies = [
name = "rustc_driver_impl"
version = "0.0.0"
dependencies = [
"ctrlc",
"libc",
"rustc_ast",
"rustc_ast_lowering",
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::const_eval::CheckAlignment;
use std::borrow::Cow;
use std::sync::atomic::Ordering::Relaxed;

use either::{Left, Right};

use rustc_data_structures::CTRL_C_RECEIVED;
use rustc_hir::def::DefKind;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
Expand Down Expand Up @@ -66,7 +68,11 @@ fn eval_body_using_ecx<'mir, 'tcx>(
)?;

// The main interpreter loop.
while ecx.step()? {}
while ecx.step()? {
if CTRL_C_RECEIVED.load(Relaxed) {
throw_exhaust!(Interrupted);
}
}

// Intern the result
let intern_kind = if cid.promoted.is_some() {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ extern crate cfg_if;
#[macro_use]
extern crate rustc_macros;

use std::sync::atomic::AtomicBool;

pub use rustc_index::static_assert_size;

#[inline(never)]
Expand Down Expand Up @@ -129,3 +131,8 @@ impl<F: FnOnce()> Drop for OnDrop<F> {
// See comments in src/librustc_middle/lib.rs
#[doc(hidden)]
pub fn __noop_fix_for_27438() {}

/// `rustc_driver::main` installs a handler that will set this to `true` if
/// the compiler has been sent a request to shut down, such as by a Ctrl-C.
/// This static is placed here so that it is available to all parts of the compiler.
pub static CTRL_C_RECEIVED: AtomicBool = AtomicBool::new(false);
1 change: 1 addition & 0 deletions compiler/rustc_driver_impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
[lib]

[dependencies]
ctrlc = "3.3.0"
tracing = { version = "0.1.35" }
serde_json = "1.0.59"
rustc_log = { path = "../rustc_log" }
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use rustc_data_structures::profiling::{
get_resident_set_size, print_time_passes_entry, TimePassesFormat,
};
use rustc_data_structures::sync::SeqCst;
use rustc_data_structures::CTRL_C_RECEIVED;
use rustc_errors::registry::{InvalidErrorCode, Registry};
use rustc_errors::{
DiagnosticMessage, ErrorGuaranteed, Handler, PResult, SubdiagnosticMessage, TerminalUrl,
Expand Down Expand Up @@ -55,6 +56,7 @@ use std::panic::{self, catch_unwind};
use std::path::PathBuf;
use std::process::{self, Command, Stdio};
use std::str;
use std::sync::atomic::Ordering::Relaxed;
use std::sync::OnceLock;
use std::time::Instant;

Expand Down Expand Up @@ -1403,6 +1405,19 @@ pub fn main() -> ! {
signal_handler::install();
let mut callbacks = TimePassesCallbacks::default();
install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());

ctrlc::set_handler(move || {
// Indicate that we have been signaled to stop. If we were already signaled, exit
// immediately. In our interpreter loop we try to consult this value often, but if for
// whatever reason we don't get to that check or the cleanup we do upon finding that
// this bool has become true takes a long time, the exit here will promptly exit the
// process on the second Ctrl-C.
if CTRL_C_RECEIVED.swap(true, Relaxed) {
std::process::exit(1);
}
})
.expect("Unable to install ctrlc handler");

let exit_code = catch_with_exit_code(|| {
let args = env::args_os()
.enumerate()
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,8 @@ pub enum ResourceExhaustionInfo {
MemoryExhausted,
/// The address space (of the target) is full.
AddressSpaceFull,
/// The compiler got an interrupt signal (a user ran out of patience).
Interrupted,
}

impl fmt::Display for ResourceExhaustionInfo {
Expand All @@ -491,6 +493,7 @@ impl fmt::Display for ResourceExhaustionInfo {
AddressSpaceFull => {
write!(f, "there are no more free addresses in the address space")
}
Interrupted => write!(f, "compilation was interrupted"),
}
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/tools/miri/src/concurrency/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::num::TryFromIntError;
use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
use std::sync::atomic::Ordering::Relaxed;
use std::task::Poll;
use std::time::{Duration, SystemTime};

use log::trace;

use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::CTRL_C_RECEIVED;
use rustc_hir::def_id::DefId;
use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::Mutability;
Expand Down Expand Up @@ -1013,21 +1014,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
/// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program
/// termination).
fn run_threads(&mut self) -> InterpResult<'tcx, !> {
static SIGNALED: AtomicBool = AtomicBool::new(false);
// In normal rustc, rustc_driver::main installs this handler. But we don't use that
// function, see src/bin/miri.rs.
ctrlc::set_handler(move || {
// Indicate that we have ben signaled to stop. If we were already signaled, exit
// Indicate that we have been signaled to stop. If we were already signaled, exit
// immediately. In our interpreter loop we try to consult this value often, but if for
// whatever reason we don't get to that check or the cleanup we do upon finding that
// this bool has become true takes a long time, the exit here will promptly exit the
// process on the second Ctrl-C.
if SIGNALED.swap(true, Relaxed) {
if CTRL_C_RECEIVED.swap(true, Relaxed) {
std::process::exit(1);
}
})
.unwrap();
.expect("Unable to install ctrlc handler");
let this = self.eval_context_mut();
loop {
if SIGNALED.load(Relaxed) {
if CTRL_C_RECEIVED.load(Relaxed) {
this.machine.handle_abnormal_termination();
std::process::exit(1);
}
Expand Down
3 changes: 3 additions & 0 deletions src/tools/tidy/src/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"crossbeam-utils",
"crypto-common",
"cstr",
"ctrlc",
"datafrog",
"derive_more",
"digest",
Expand Down Expand Up @@ -185,6 +186,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"memmap2",
"memoffset",
"miniz_oxide",
"nix",
"num_cpus",
"object",
"odht",
Expand Down Expand Up @@ -281,6 +283,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"winapi-util",
"winapi-x86_64-pc-windows-gnu",
"windows",
"windows-sys",
"windows-targets",
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
Expand Down

0 comments on commit 38a5fee

Please sign in to comment.