use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::runtime::restore_terminal;
pub struct SignalHandler {
should_exit: Arc<AtomicBool>,
}
impl SignalHandler {
pub fn new() -> Self {
Self {
should_exit: Arc::new(AtomicBool::new(false)),
}
}
pub fn should_exit_flag(&self) -> Arc<AtomicBool> {
Arc::clone(&self.should_exit)
}
pub fn should_exit(&self) -> bool {
self.should_exit.load(Ordering::SeqCst)
}
}
impl Default for SignalHandler {
fn default() -> Self {
Self::new()
}
}
pub fn install_signal_handler() -> Result<SignalHandler, ctrlc::Error> {
let handler = SignalHandler::new();
let should_exit = handler.should_exit_flag();
ctrlc::set_handler(move || {
restore_terminal();
should_exit.store(true, Ordering::SeqCst);
std::thread::sleep(std::time::Duration::from_millis(100));
std::process::exit(130); })?;
Ok(handler)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_signal_handler_creation() {
let handler = SignalHandler::new();
assert!(!handler.should_exit());
}
#[test]
fn test_signal_handler_flag_sharing() {
let handler = SignalHandler::new();
let flag = handler.should_exit_flag();
assert!(!flag.load(Ordering::SeqCst));
flag.store(true, Ordering::SeqCst);
assert!(handler.should_exit());
}
}