Skip to content

Commit 197e4ca

Browse files
committed
Print a backtrace in const eval if interrupted
1 parent cdb775c commit 197e4ca

File tree

12 files changed

+61
-13
lines changed

12 files changed

+61
-13
lines changed

Cargo.lock

+12-4
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,12 @@ dependencies = [
483483
"rustc-std-workspace-core",
484484
]
485485

486+
[[package]]
487+
name = "cfg_aliases"
488+
version = "0.1.1"
489+
source = "registry+https://github.com/rust-lang/crates.io-index"
490+
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
491+
486492
[[package]]
487493
name = "chrono"
488494
version = "0.4.34"
@@ -884,9 +890,9 @@ dependencies = [
884890

885891
[[package]]
886892
name = "ctrlc"
887-
version = "3.4.2"
893+
version = "3.4.4"
888894
source = "registry+https://github.com/rust-lang/crates.io-index"
889-
checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
895+
checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345"
890896
dependencies = [
891897
"nix",
892898
"windows-sys 0.52.0",
@@ -2519,12 +2525,13 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
25192525

25202526
[[package]]
25212527
name = "nix"
2522-
version = "0.27.1"
2528+
version = "0.28.0"
25232529
source = "registry+https://github.com/rust-lang/crates.io-index"
2524-
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
2530+
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
25252531
dependencies = [
25262532
"bitflags 2.4.2",
25272533
"cfg-if",
2534+
"cfg_aliases",
25282535
"libc",
25292536
]
25302537

@@ -3744,6 +3751,7 @@ dependencies = [
37443751
name = "rustc_driver_impl"
37453752
version = "0.0.0"
37463753
dependencies = [
3754+
"ctrlc",
37473755
"libc",
37483756
"rustc_ast",
37493757
"rustc_ast_lowering",

compiler/rustc_const_eval/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ const_eval_intern_kind = {$kind ->
146146
*[other] {""}
147147
}
148148
149+
const_eval_interrupted = compilation was interrupted
150+
149151
const_eval_invalid_align_details =
150152
invalid align passed to `{$name}`: {$align} is {$err_kind ->
151153
[not_power_of_two] not a power of 2

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
use std::sync::atomic::Ordering::Relaxed;
2+
13
use either::{Left, Right};
24

5+
use rustc_data_structures::CTRL_C_RECEIVED;
36
use rustc_hir::def::DefKind;
47
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
58
use rustc_middle::mir::{self, ConstAlloc, ConstValue};
@@ -79,7 +82,11 @@ fn eval_body_using_ecx<'mir, 'tcx>(
7982
ecx.storage_live_for_always_live_locals()?;
8083

8184
// The main interpreter loop.
82-
while ecx.step()? {}
85+
while ecx.step()? {
86+
if CTRL_C_RECEIVED.load(Relaxed) {
87+
throw_exhaust!(Interrupted);
88+
}
89+
}
8390

8491
// Intern the result
8592
intern_const_alloc_recursive(ecx, intern_kind, &ret)?;

compiler/rustc_const_eval/src/errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ impl ReportErrorExt for ResourceExhaustionInfo {
882882
ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached,
883883
ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted,
884884
ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full,
885+
ResourceExhaustionInfo::Interrupted => const_eval_interrupted,
885886
}
886887
}
887888
fn add_args<G: EmissionGuarantee>(self, _: &mut Diag<'_, G>) {}

compiler/rustc_data_structures/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ extern crate tracing;
4646
extern crate rustc_macros;
4747

4848
use std::fmt;
49+
use std::sync::atomic::AtomicBool;
4950

5051
pub use rustc_index::static_assert_size;
5152

@@ -161,3 +162,8 @@ macro_rules! external_bitflags_debug {
161162
}
162163
};
163164
}
165+
166+
/// `rustc_driver::main` installs a handler that will set this to `true` if
167+
/// the compiler has been sent a request to shut down, such as by a Ctrl-C.
168+
/// This static is placed here so that it is available to all parts of the compiler.
169+
pub static CTRL_C_RECEIVED: AtomicBool = AtomicBool::new(false);

compiler/rustc_driver_impl/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
# tidy-alphabetical-start
8+
ctrlc = "3.4.4"
89
rustc_ast = { path = "../rustc_ast" }
910
rustc_ast_lowering = { path = "../rustc_ast_lowering" }
1011
rustc_ast_passes = { path = "../rustc_ast_passes" }

compiler/rustc_driver_impl/src/lib.rs

+14
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
2222
use rustc_data_structures::profiling::{
2323
get_resident_set_size, print_time_passes_entry, TimePassesFormat,
2424
};
25+
use rustc_data_structures::CTRL_C_RECEIVED;
2526
use rustc_errors::emitter::stderr_destination;
2627
use rustc_errors::registry::Registry;
2728
use rustc_errors::{
@@ -1515,6 +1516,19 @@ pub fn main() -> ! {
15151516
signal_handler::install();
15161517
let mut callbacks = TimePassesCallbacks::default();
15171518
let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
1519+
1520+
ctrlc::set_handler(move || {
1521+
// Indicate that we have been signaled to stop. If we were already signaled, exit
1522+
// immediately. In our interpreter loop we try to consult this value often, but if for
1523+
// whatever reason we don't get to that check or the cleanup we do upon finding that
1524+
// this bool has become true takes a long time, the exit here will promptly exit the
1525+
// process on the second Ctrl-C.
1526+
if CTRL_C_RECEIVED.swap(true, Ordering::Relaxed) {
1527+
std::process::exit(1);
1528+
}
1529+
})
1530+
.expect("Unable to install ctrlc handler");
1531+
15181532
let exit_code = catch_with_exit_code(|| {
15191533
RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks)
15201534
.set_using_internal_features(using_internal_features)

compiler/rustc_middle/src/mir/interpret/error.rs

+2
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,8 @@ pub enum ResourceExhaustionInfo {
482482
MemoryExhausted,
483483
/// The address space (of the target) is full.
484484
AddressSpaceFull,
485+
/// The compiler got an interrupt signal (a user ran out of patience).
486+
Interrupted,
485487
}
486488

487489
/// A trait for machine-specific errors (or other "machine stop" conditions).

src/tools/miri/src/concurrency/thread.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
use std::cell::RefCell;
44
use std::collections::hash_map::Entry;
55
use std::num::TryFromIntError;
6-
use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
6+
use std::sync::atomic::Ordering::Relaxed;
77
use std::task::Poll;
88
use std::time::{Duration, SystemTime};
99

1010
use either::Either;
1111

1212
use rustc_data_structures::fx::FxHashMap;
13+
use rustc_data_structures::CTRL_C_RECEIVED;
1314
use rustc_hir::def_id::DefId;
1415
use rustc_index::{Idx, IndexVec};
1516
use rustc_middle::mir::Mutability;
@@ -1045,21 +1046,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
10451046
/// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program
10461047
/// termination).
10471048
fn run_threads(&mut self) -> InterpResult<'tcx, !> {
1048-
static SIGNALED: AtomicBool = AtomicBool::new(false);
1049+
// In normal rustc, rustc_driver::main installs this handler. But we don't use that
1050+
// function, see src/bin/miri.rs.
10491051
ctrlc::set_handler(move || {
1050-
// Indicate that we have ben signaled to stop. If we were already signaled, exit
1052+
// Indicate that we have been signaled to stop. If we were already signaled, exit
10511053
// immediately. In our interpreter loop we try to consult this value often, but if for
10521054
// whatever reason we don't get to that check or the cleanup we do upon finding that
10531055
// this bool has become true takes a long time, the exit here will promptly exit the
10541056
// process on the second Ctrl-C.
1055-
if SIGNALED.swap(true, Relaxed) {
1057+
if CTRL_C_RECEIVED.swap(true, Relaxed) {
10561058
std::process::exit(1);
10571059
}
10581060
})
1059-
.unwrap();
1061+
.expect("Unable to install ctrlc handler");
10601062
let this = self.eval_context_mut();
10611063
loop {
1062-
if SIGNALED.load(Relaxed) {
1064+
if CTRL_C_RECEIVED.load(Relaxed) {
10631065
this.machine.handle_abnormal_termination();
10641066
std::process::exit(1);
10651067
}

src/tools/tidy/src/deps.rs

+3
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
208208
"byteorder", // via ruzstd in object in thorin-dwp
209209
"cc",
210210
"cfg-if",
211+
"cfg_aliases",
211212
"compiler_builtins",
212213
"cpufeatures",
213214
"crc32fast",
@@ -216,6 +217,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
216217
"crossbeam-epoch",
217218
"crossbeam-utils",
218219
"crypto-common",
220+
"ctrlc",
219221
"darling",
220222
"darling_core",
221223
"darling_macro",
@@ -281,6 +283,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
281283
"memmap2",
282284
"memoffset",
283285
"miniz_oxide",
286+
"nix",
284287
"nu-ansi-term",
285288
"num-conv",
286289
"num_cpus",

tests/run-make/jobserver-error/Makefile

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ include ../tools.mk
44
# ignore-cross-compile
55

66
# Test compiler behavior in case environment specifies wrong jobserver.
7+
# Note that by default, the compiler uses file descriptors 0 (stdin), 1 (stdout), 2 (stderr),
8+
# but also 3 and 4 for either end of the ctrl-c signal handler self-pipe.
79

810
all:
9-
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr -
11+
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=5,5" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr -
1012
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3</dev/null' 2>&1 | diff not_a_pipe.stderr -
1113

1214
# This test randomly fails, see https://github.com/rust-lang/rust/issues/110321

tests/run-make/jobserver-error/cannot_open_fd.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=3,3"`: cannot open file descriptor 3 from the jobserver environment variable value: Bad file descriptor (os error 9)
1+
warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=5,5"`: cannot open file descriptor 5 from the jobserver environment variable value: Bad file descriptor (os error 9)
22
|
33
= note: the build environment is likely misconfigured
44

0 commit comments

Comments
 (0)