//! Safe frontend SIGINT subscription for the synchronous worker lifecycle. use std::{ io, sync::{ Arc, atomic::{AtomicU32, Ordering}, }, thread, }; use signal_hook::{consts::signal::SIGINT, iterator::Signals}; use super::Cancellation; /// Process-wide interrupt count observed by the production CLI frontend. #[derive(Clone, Debug)] pub struct InterruptCounter { count: Arc, } impl InterruptCounter { /// Installs a safe SIGINT iterator and detached counter thread. pub fn install() -> io::Result { let mut signals = Signals::new([SIGINT])?; let count = Arc::new(AtomicU32::new(0)); let thread_count = Arc::clone(&count); thread::Builder::new() .name("ghidr-sigint".to_owned()) .spawn(move || { for _signal in signals.forever() { let _previous = thread_count.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |value| { Some(value.saturating_add(1)) }); } })?; Ok(Self { count }) } } impl Cancellation for InterruptCounter { fn interrupt_count(&self) -> u32 { self.count.load(Ordering::SeqCst) } }