From 15501132916dfbc24f23b619e6d5408f258fc0d9 Mon Sep 17 00:00:00 2001 From: Jonas Maier <> Date: Wed, 11 Mar 2026 12:30:07 +0100 Subject: can wait for threads & processes with a timeout now --- src/ctrlc.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/ctrlc.rs (limited to 'src/ctrlc.rs') diff --git a/src/ctrlc.rs b/src/ctrlc.rs new file mode 100644 index 0000000..4c0153a --- /dev/null +++ b/src/ctrlc.rs @@ -0,0 +1,63 @@ +use crate::Session; +use libc::c_int; +use nix::sys::signal::*; +use std::sync::*; + +static SESSION: Mutex>>> = Mutex::new(None); + +fn handle() { + let Ok(mut se) = SESSION.lock() else { return }; + let Some(se) = se.as_mut() else { return }; + let Ok(mut se) = se.lock() else { return }; + se.ctrlc.pressed = true; +} + +extern "C" fn c_handle(_signal: c_int) { + // cannot propagate panic into C-land + let _ = std::panic::catch_unwind(|| { + if let Err(e) = std::panic::catch_unwind(handle) { + eprintln!("{e:?}"); // might panic + } + }); +} + +#[derive(Default)] +pub struct CtrlC { + pressed: bool, +} + +struct Teardown; +impl Drop for Teardown { + fn drop(&mut self) { + teardown(); + } +} + +fn teardown() { + unsafe { + let _ = signal(Signal::SIGINT, SigHandler::SigDfl); + } + if let Ok(mut se) = SESSION.lock() { + *se = None; + } +} + +#[must_use] +pub fn setup(session: Arc>) -> impl Drop { + *SESSION.lock().unwrap() = Some(session); + unsafe { + signal(Signal::SIGINT, SigHandler::Handler(c_handle)) + .expect("failed to set ctrl+c signal handler"); + } + Teardown +} + +pub fn peek(session: &Session) -> bool { + session.ctrlc.pressed +} + +pub fn pop(session: &mut Session) -> bool { + let x = session.ctrlc.pressed; + session.ctrlc.pressed = false; + x +} -- cgit v1.2.3