aboutsummaryrefslogtreecommitdiffstats
path: root/src/ctrlc.rs
diff options
context:
space:
mode:
authorJonas Maier <>2026-03-11 12:30:07 +0100
committerJonas Maier <>2026-03-11 12:30:07 +0100
commit15501132916dfbc24f23b619e6d5408f258fc0d9 (patch)
treea77e27bfc139415baf7faf09eeaefec360db9423 /src/ctrlc.rs
parentb881eec59118bc630b64378476f4d5ada2bf5968 (diff)
downloadpish-15501132916dfbc24f23b619e6d5408f258fc0d9.tar.gz
can wait for threads & processes with a timeout now
Diffstat (limited to 'src/ctrlc.rs')
-rw-r--r--src/ctrlc.rs63
1 files changed, 63 insertions, 0 deletions
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<Option<Arc<Mutex<Session>>>> = 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<Mutex<Session>>) -> 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
+}