Skip to content

Commit aee196f

Browse files
committed
Auto merge of rust-lang#2899 - saethlin:measureme-cleanup, r=RalfJung
Try to ensure measureme output is valid when the interpreter is interrupted Dropping our `measureme::Profiler` will have the profiler flush its output buffer and write out its string table. If the profiler's `Drop` impl does not run, the output file is not usable. This approach has zero runtime overhead.
2 parents a4fb414 + 56eb087 commit aee196f

File tree

4 files changed

+56
-0
lines changed

4 files changed

+56
-0
lines changed

src/tools/miri/Cargo.lock

+29
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,16 @@ dependencies = [
183183
"cfg-if",
184184
]
185185

186+
[[package]]
187+
name = "ctrlc"
188+
version = "3.2.5"
189+
source = "registry+https://github.com/rust-lang/crates.io-index"
190+
checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639"
191+
dependencies = [
192+
"nix",
193+
"windows-sys 0.45.0",
194+
]
195+
186196
[[package]]
187197
name = "diff"
188198
version = "0.1.13"
@@ -421,6 +431,7 @@ name = "miri"
421431
version = "0.1.0"
422432
dependencies = [
423433
"colored",
434+
"ctrlc",
424435
"env_logger",
425436
"getrandom",
426437
"lazy_static",
@@ -437,6 +448,18 @@ dependencies = [
437448
"ui_test",
438449
]
439450

451+
[[package]]
452+
name = "nix"
453+
version = "0.26.2"
454+
source = "registry+https://github.com/rust-lang/crates.io-index"
455+
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
456+
dependencies = [
457+
"bitflags",
458+
"cfg-if",
459+
"libc",
460+
"static_assertions",
461+
]
462+
440463
[[package]]
441464
name = "object"
442465
version = "0.30.3"
@@ -713,6 +736,12 @@ version = "1.10.0"
713736
source = "registry+https://github.com/rust-lang/crates.io-index"
714737
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
715738

739+
[[package]]
740+
name = "static_assertions"
741+
version = "1.1.0"
742+
source = "registry+https://github.com/rust-lang/crates.io-index"
743+
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
744+
716745
[[package]]
717746
name = "syn"
718747
version = "2.0.15"

src/tools/miri/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ smallvec = "1.7"
2929
# for more information.
3030
rustc-workspace-hack = "1.0.0"
3131
measureme = "10.0.0"
32+
ctrlc = "3.2.5"
3233

3334
[target.'cfg(unix)'.dependencies]
3435
libc = "0.2"

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

+17
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
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};
67
use std::task::Poll;
78
use std::time::{Duration, SystemTime};
89

@@ -1012,8 +1013,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
10121013
/// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program
10131014
/// termination).
10141015
fn run_threads(&mut self) -> InterpResult<'tcx, !> {
1016+
static SIGNALED: AtomicBool = AtomicBool::new(false);
1017+
ctrlc::set_handler(move || {
1018+
// Indicate that we have ben signaled to stop. If we were already signaled, exit
1019+
// immediately. In our interpreter loop we try to consult this value often, but if for
1020+
// whatever reason we don't get to that check or the cleanup we do upon finding that
1021+
// this bool has become true takes a long time, the exit here will promptly exit the
1022+
// process on the second Ctrl-C.
1023+
if SIGNALED.swap(true, Relaxed) {
1024+
std::process::exit(1);
1025+
}
1026+
})
1027+
.unwrap();
10151028
let this = self.eval_context_mut();
10161029
loop {
1030+
if SIGNALED.load(Relaxed) {
1031+
this.machine.handle_abnormal_termination();
1032+
std::process::exit(1);
1033+
}
10171034
match this.machine.threads.schedule(&this.machine.clock)? {
10181035
SchedulingAction::ExecuteStep => {
10191036
if !this.step()? {

src/tools/miri/src/machine.rs

+9
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,15 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
713713
let def_id = frame.instance.def_id();
714714
def_id.is_local() || self.local_crates.contains(&def_id.krate)
715715
}
716+
717+
/// Called when the interpreter is going to shut down abnormally, such as due to a Ctrl-C.
718+
pub(crate) fn handle_abnormal_termination(&mut self) {
719+
// All strings in the profile data are stored in a single string table which is not
720+
// written to disk until the profiler is dropped. If the interpreter exits without dropping
721+
// the profiler, it is not possible to interpret the profile data and all measureme tools
722+
// will panic when given the file.
723+
drop(self.profiler.take());
724+
}
716725
}
717726

718727
impl VisitTags for MiriMachine<'_, '_> {

0 commit comments

Comments
 (0)