addy/
lib.rs

1//! # Addy
2//! A library for ergonomically handling kernel interrupts.
3//!
4//! ## Quick Start
5//! ```no_run
6//! use addy::SIGWINCH;
7//! use std::io::{Read, stdin};
8//! fn main() -> Result<(), addy::Error> {
9//! 	/* SIGWINCH is a POSIX interrupt signal for window resized */
10//! 	addy::mediate(SIGWINCH)
11//! 			.register("print", |_signal| { println!("Screen Resized!"); })?
12//! 			.enable()?;
13//!
14//! 	/* Block so the program doesn't exit immediately
15//! 	 * Try resizing your terminal window :)
16//! 	*/
17//! 	let mut buffer = [0; 1];
18//!    	loop {
19//!        stdin().read(&mut buffer);
20//!   	}
21//! 	Ok(())
22//! }
23//! ```
24//!
25//! # Things To Know
26//! I love you and I wish the best for you. No matter what you choose to do, I hope you decide it is worth you time to do it well.
27//!
28//! ## Addy is Thread Safe!
29//! You can call it from anywhere, at anytime! You can store a SignalHandle (returned from addy::mediate(signal)) in a variable and pass it around.
30//! ```no_run
31//! use addy::{SIGWINCH, SIGINT};
32//! use std::io::{Read, stdin};
33//! static QUOTE: &'static str = "Look at you, hacker: a pathetic creature of meat \
34//! 							  and bone, panting and sweating as you run through \
35//! 							  my corridors. How can you challenge a perfect, \
36//! 							  immortal machine?";
37//!
38//! fn main() -> Result<(), addy::Error> {
39//! 	/* When the window resizes */
40//!     addy::mediate(SIGWINCH)
41//!     		.register("hello", |_signal| { println!("Hello, World!"); })?
42//!     		.register("girls", |_signal| { println!("Hello, Girls!"); })?
43//!     		.enable()?;
44//!
45//!     /* SIGINT is sent when the user presses Ctrl + C. The default behavior is
46//!      * to interrupt the program's execution.
47//!     */
48//!     let mut ctrl_c = addy::mediate(SIGINT);
49//!     ctrl_c.register("no_interruptions", |_signal| { println!("{}", QUOTE); })?.enable()?;
50//!
51//!     /* Let the user use Ctrl + C to kill the program after 10 seconds */
52//!     std::thread::spawn(move || -> Result<(), addy::Error> {
53//!         std::thread::sleep(std::time::Duration::from_secs(10));
54//!         ctrl_c.default()?;
55//!         Ok(())
56//!     });
57//!
58//!     /* Stop saying "Hello, World!" on resize after 5 seconds */
59//!     std::thread::spawn(move || -> Result<(), addy::Error> {
60//!         std::thread::sleep(std::time::Duration::from_secs(5));
61//!         addy::mediate(SIGWINCH).remove("hello")?;
62//!         Ok(())
63//!     });
64//!
65//!     /* Capture the input so we don't exit the program immediately */
66//!     let mut buffer = [0; 1];
67//!     loop {
68//!         stdin().read(&mut buffer);
69//!     }
70//!
71//!     Ok(())
72//! }
73//! ```
74//! ## Errors
75//! If the MPSC channel closes, of the Event Loop thread closes, there is no way to recover and any future Addy calls will return an addy::Error.
76
77#![deny(
78    missing_docs,
79    missing_debug_implementations,
80    missing_copy_implementations,
81    trivial_casts,
82    trivial_numeric_casts,
83    unstable_features,
84    unused_import_braces,
85    unused_qualifications
86)]
87
88/* Standard Library */
89use std::convert::TryFrom;
90use std::sync::{
91    mpsc::{self, Sender},
92    Mutex, Once,
93};
94use std::thread;
95
96/* Std Lib Adjacent Crates */
97use lazy_static::lazy_static;
98use libc;
99
100/* Thrid Party Crates */
101use fnv::FnvHashMap; // Faster for the interger keys we're using
102
103/**********
104 * ERRORS *
105 **********/
106/* Use our own error instead of passing the SendError<Action> so we don't have
107 * expose the Action enum publicly.
108*/
109#[derive(Debug, Clone, Copy)]
110/// Addy Error type - realistically you will never see it. As it only occurs
111/// when the MPSC channel fails. MPSC channels only fail if the receiver is
112/// dropped which can only happen if the event loop thread panics somehow.
113///
114/// If it does fail, there is no way to recover, future Addy calls will fail.
115pub enum Error {
116    /// Returned when a function call on a SignalHandler fails.
117    CallFailed,
118}
119
120impl std::fmt::Display for Error {
121    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122        match self {
123            Error::CallFailed => write!(
124                f,
125                "Addy function call failed to send. The MPSC and/or event loop thread has closed."
126            ),
127        }
128    }
129}
130
131impl std::error::Error for Error {
132    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
133        None
134    }
135}
136
137/***********
138 * ACTIONS *
139 ***********/
140
141/* Used by the MPSC channel to instruct what the Event Loop should do when
142 * it wakes up.
143 *
144 * ==========================================================================
145 *
146 * CBPointer is a how Addy represents "pointers" to the callbacks the caller
147 * passes in with .register()
148 *
149 * CBP wraps CBPointer so Debug can be implemented for it
150*/
151type CBPointer = Box<dyn Fn(Signal) -> () + Send>;
152struct CBP(CBPointer);
153impl std::fmt::Debug for CBP {
154    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155        f.write_str("CBPointer")
156    }
157}
158
159/* This enum is what is message passed to the Event Loop to tell it what
160 * action to take.
161*/
162#[derive(Debug)]
163enum Action {
164    // Used by fn c_handler(...) to tell the Event Loop an interrupt occured
165    Call(Signal),
166    // Used by SignalHandle to add a named callback for the associated interrupt
167    Register(Signal, String, CBP),
168    // Used by SignalHandle to remove a named callback from the associated interrupt
169    Remove(Signal, String),
170    /* Used by SignalHandle to clear all the callbacks from the associated
171     * intterupt. This effectively ignores the interrupt, but the signal is
172     * still handled by this library and the signal handler. If you're clearing
173     * to stop callbacks, but don't plan on adding anymore use Release instead.
174    	*/
175    Clear(Signal),
176    // Used by SignalHandle to prevent the default signal behavior from occurring
177    Ignore(Signal),
178    /* Used by SignalHandle to restore the interrupt handler to the default
179     * behavior (like terminating your program). Some interrupt's default
180     * behavior is to be ignored.
181    	*/
182    Default(Signal),
183    /* Used by SignalHandle to stop handling the associated interrupt. Resets
184     * the interrupts behavior to default and clears all callbacks.
185    	*/
186    Release(Signal),
187    /* Used by SignalHandle to tell Addy to resume handling this intterupt.
188     * e.g. if you registered 3 callbacks, then set the interrupt handler to
189     * .ignore() or .default(), then later called .resume() the 3 callbacks
190     * would be called again when the interrupt occurs.
191     *
192     * This is also aliased by SignalHandle .enable() to start capturing the
193     * interrupt.
194    	*/
195    Resume(Signal),
196}
197
198/***********
199 * SIGNALS *
200 ***********/
201
202/* Most of this section is ripped & modified from the nix* crate so I didn't
203 * have to retype every signal and look up every architecture difference.
204 *
205 * Crate: https://crates.io/crates/nix
206 * Source: https://github.com/nix-rust/nix/blob/7a5248c70a4ad0ef1ff1b385a7674b38403386df/src/sys/signal.rs#L20
207 * License: (MIT) - https://github.com/nix-rust/nix/blob/master/LICENSE
208 *
209 * Representing the Signals as i32 (libc::c_int) so we can use Rust's features
210 * around enums.
211*/
212
213/* Required to we can use them in our callback HashMaps */
214/// Enum representing the different interrupt signals
215///
216/// # Signals Supported
217/// Not all signals are supported on all platforms/architectures. Which signals
218/// does your platform support? Run: `kill -l` to find out!
219///
220/// * SIGHUP
221/// * SIGINT
222/// * SIGQUIT
223/// * SIGILL
224/// * SIGTRAP
225/// * SIGABRT
226/// * SIGBUS
227/// * SIGFPE
228/// * SIGKILL
229/// * SIGUSR1
230/// * SIGSEGV
231/// * SIGUSR2
232/// * SIGPIPE
233/// * SIGALRM
234/// * SIGTERM
235/// * SIGSTKF
236/// * SIGCHLD
237/// * SIGCONT
238/// * SIGSTOP
239/// * SIGTSTP
240/// * SIGTTIN
241/// * SIGTTOU
242/// * SIGURG
243/// * SIGXCPU
244/// * SIGXFSZ
245/// * SIGVTAL
246/// * SIGPROF
247/// * SIGWINC
248/// * SIGIO  
249/// * SIGPWR
250/// * SIGSYS
251/// * SIGEMT
252/// * SIGINFO
253#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
254#[repr(i32)]
255pub enum Signal {
256    /// Hangup detected on controlling terminal or death of controlling process
257    SIGHUP = libc::SIGHUP,
258    /// Interrupt from keyboard
259    SIGINT = libc::SIGINT,
260    /// Quit from keyboard
261    SIGQUIT = libc::SIGQUIT,
262    /// Illegal Instruction
263    SIGILL = libc::SIGILL,
264    /// Trace/breakpoint trap
265    SIGTRAP = libc::SIGTRAP,
266    /// Abort signal from abort(3)
267    SIGABRT = libc::SIGABRT,
268    /// Bus error (bad memory access)
269    SIGBUS = libc::SIGBUS,
270    /// Floating-point exception
271    SIGFPE = libc::SIGFPE,
272    /// Kill signal
273    SIGKILL = libc::SIGKILL,
274    /// User-defined signal 1
275    SIGUSR1 = libc::SIGUSR1,
276    /// Invalid memory reference
277    SIGSEGV = libc::SIGSEGV,
278    /// User-defined signal 2
279    SIGUSR2 = libc::SIGUSR2,
280    /// Broken pipe: write to pipe with no readers
281    SIGPIPE = libc::SIGPIPE,
282    /// Timer signal from alarm(2)
283    SIGALRM = libc::SIGALRM,
284    /// Termination signal
285    SIGTERM = libc::SIGTERM,
286    /// Stack fault on coprocessor.
287    #[cfg(all(
288        any(target_os = "android", target_os = "emscripten", target_os = "linux"),
289        not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))
290    ))]
291    SIGSTKFLT = libc::SIGSTKFLT,
292    /// Child stopped or terminated
293    SIGCHLD = libc::SIGCHLD,
294    /// Continue if stopped
295    SIGCONT = libc::SIGCONT,
296    /// Stop process
297    SIGSTOP = libc::SIGSTOP,
298    /// Stop typed at terminal
299    SIGTSTP = libc::SIGTSTP,
300    /// Terminal input for background process
301    SIGTTIN = libc::SIGTTIN,
302    /// Terminal output for background process
303    SIGTTOU = libc::SIGTTOU,
304    /// Urgent condition on socket (4.2BSD)
305    SIGURG = libc::SIGURG,
306    /// CPU time limit exceeded (4.2BSD)
307    SIGXCPU = libc::SIGXCPU,
308    /// File size limit exceeded (4.2BSD)
309    SIGXFSZ = libc::SIGXFSZ,
310    /// Virtual alarm clock (4.2BSD)
311    SIGVTALRM = libc::SIGVTALRM,
312    /// Profiling timer expired
313    SIGPROF = libc::SIGPROF,
314    /// Window resize signal (4.3BSD, Sun)
315    SIGWINCH = libc::SIGWINCH,
316    /// I/O now possible (4.2BSD)
317    SIGIO = libc::SIGIO,
318    /// Power failure (System V)
319    #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
320    SIGPWR = libc::SIGPWR,
321    /// Bad system call (SVr4)
322    SIGSYS = libc::SIGSYS,
323    /// Emulator trap
324    #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
325    SIGEMT = libc::SIGEMT,
326    /// A synonym for SIGPWR
327    #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
328    SIGINFO = libc::SIGINFO,
329}
330
331/* Re-export all the Signals without the prefix.
332 * Mad that I didn't know you could do this, I had a Signal enum and switched to
333 * constants for aesthetic reasons.
334*/
335pub use self::Signal::*;
336
337impl Signal {
338    /* Used so Signal can implement Display */
339
340    /// Returns name of signal.
341    ///
342    /// This function is equivalent to `<Signal as AsRef<str>>::as_ref()`,
343    /// with difference that returned string is `'static`
344    /// and not bound to `self`'s lifetime.
345    ///
346    /// # Example
347    /// ```
348    /// use addy::SIGINT;
349    ///
350    /// fn main() {
351    /// 	println!("My favorite interrupt is: {}", SIGINT);
352    /// }
353    /// ```
354    pub fn as_str(self) -> &'static str {
355        match self {
356            SIGHUP => "SIGHUP",
357            SIGINT => "SIGINT",
358            SIGQUIT => "SIGQUIT",
359            SIGILL => "SIGILL",
360            SIGTRAP => "SIGTRAP",
361            SIGABRT => "SIGABRT",
362            SIGBUS => "SIGBUS",
363            SIGFPE => "SIGFPE",
364            SIGKILL => "SIGKILL",
365            SIGUSR1 => "SIGUSR1",
366            SIGSEGV => "SIGSEGV",
367            SIGUSR2 => "SIGUSR2",
368            SIGPIPE => "SIGPIPE",
369            SIGALRM => "SIGALRM",
370            SIGTERM => "SIGTERM",
371            #[cfg(all(
372                any(target_os = "android", target_os = "emscripten", target_os = "linux"),
373                not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))
374            ))]
375            SIGSTKFLT => "SIGSTKFLT",
376            SIGCHLD => "SIGCHLD",
377            SIGCONT => "SIGCONT",
378            SIGSTOP => "SIGSTOP",
379            SIGTSTP => "SIGTSTP",
380            SIGTTIN => "SIGTTIN",
381            SIGTTOU => "SIGTTOU",
382            SIGURG => "SIGURG",
383            SIGXCPU => "SIGXCPU",
384            SIGXFSZ => "SIGXFSZ",
385            SIGVTALRM => "SIGVTALRM",
386            SIGPROF => "SIGPROF",
387            SIGWINCH => "SIGWINCH",
388            SIGIO => "SIGIO",
389            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
390            SIGPWR => "SIGPWR",
391            SIGSYS => "SIGSYS",
392            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
393            SIGEMT => "SIGEMT",
394            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
395            SIGINFO => "SIGINFO",
396        }
397    }
398}
399
400impl AsRef<str> for Signal {
401    fn as_ref(&self) -> &str {
402        self.as_str()
403    }
404}
405
406/* We can now print the Signal */
407impl std::fmt::Display for Signal {
408    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
409        f.write_str(self.as_ref())
410    }
411}
412
413/* Array of Signal, platform dependent */
414#[cfg(all(
415    any(target_os = "linux", target_os = "android", target_os = "emscripten"),
416    not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))
417))]
418const SIGNALS: [Signal; 31] = [
419    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV,
420    SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGSTKFLT, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN,
421    SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
422];
423
424#[cfg(all(
425    any(target_os = "linux", target_os = "android", target_os = "emscripten"),
426    any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")
427))]
428const SIGNALS: [Signal; 30] = [
429    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV,
430    SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU,
431    SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
432];
433
434#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))]
435const SIGNALS: [Signal; 31] = [
436    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV,
437    SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU,
438    SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGSYS, SIGEMT, SIGINFO,
439];
440
441/* Count of the above signal constants + 1. Used to create HashMaps.with_capacity()
442 * and with from libc::c_int for array bounds checking.
443*/
444const NUM_SIGNALS: libc::c_int = 32;
445
446/*******************
447 * SIGNAL ITERATOR *
448 *******************/
449
450/// Useful if you want to set every signal to "Ignore" or "Default."
451///
452/// # Example
453/// ```
454/// use addy::Signal;
455///
456/// fn main() -> Result<(), addy::Error> {
457/// 	/* Have each intterupt print itself */
458///     for signal in Signal::iterator() {
459/// 		addy::mediate(signal).register("reflexive", |signal| {
460///				println!("Signal: {}", signal);
461///			})?;
462///		}
463///		Ok(())
464/// }
465/// ```
466#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
467pub struct SignalIterator {
468    next: usize,
469}
470
471impl Iterator for SignalIterator {
472    type Item = Signal;
473
474    fn next(&mut self) -> Option<Signal> {
475        if self.next < SIGNALS.len() {
476            let next_signal = SIGNALS[self.next];
477            self.next += 1;
478            Some(next_signal)
479        } else {
480            None
481        }
482    }
483}
484
485impl Signal {
486    /// Returns an iterator over the different Signals
487    pub fn iterator() -> SignalIterator {
488        SignalIterator { next: 0 }
489    }
490}
491
492/******************
493 * C FFI CALLBACK *
494 ******************/
495
496/* This is the callback passed to the C FF sigaction(...) - it is called with
497 * three arguments. We only care about what signal was called so we free() the
498 * other two, grab a copy of Sender and message pass what signal was called to
499 * the Event Loop.
500*/
501type CVoid = *mut libc::c_void;
502fn c_handler(signal: Signal, _info: CVoid, _ucontext: CVoid) {
503    /* We're the only function that interacts with this global static copy of
504     * a sender to the Event Loop. We only read from this location, only one
505     * interrupt can be active at a time so this is SAFE.
506    	*/
507    let sender;
508    unsafe {
509        sender = SENDER.as_ref().unwrap().clone();
510    }
511
512    /* Drop the error since we can't return one from across the kernel
513     * boundary.
514    	*/
515    let _ = sender.send(Action::Call(signal));
516}
517
518/*****************
519 * SIGNAL HANDLE *
520 *****************/
521
522/// This is the struct returned from an addy::mediate(Signal) call. It allows
523/// the caller to add, remove, and clear callbacks to the provided interrupt
524/// handler. Adding closures prevents the default bevaior (if any).
525///
526/// You can also set the interrupt to the default behaviour, or to be ignored by
527/// the process. If you set a signal to be ignored or back to the defaults you
528/// can call .resume() to to have it handle your callbacks again.
529///
530/// Dropping it does _not_ stop the signal handler. You must call .release() to
531/// have Addy stop handling this interrupt and free the associated resources.
532/// Conversely, you don't have to keep a handle to this around once you've set
533/// it up.
534///
535/// If you register callbacks for an interrupt, you must call .enable() to have
536/// them run. If you call .release() on a SignalHandler you must call .enable()
537/// again (after re-registering new callbacks).
538///
539/// # Example
540/// ```
541/// use addy::{Signal, SIGWINCH};
542///
543/// fn my_func(signal: Signal) {
544/// 	/* Does a thing */
545/// }
546///
547/// fn main() -> Result<(), addy::Error> {
548/// 	addy::mediate(SIGWINCH)
549///				.register("print", |_signal| { println!("Screen Resized!"); })?
550///				.register("my_func", my_func)?
551///				.enable()?;
552///
553///		//-- Later --//
554///
555///		// Ignore the incoming signal
556/// 	addy::mediate(SIGWINCH).ignore()?;
557///
558///		//-- Later Still --//
559///
560///		// Swap out one of the callbacks and re-enable capturing the interrupt
561/// 	addy::mediate(SIGWINCH)
562///				.remove("print")?
563/// 			.register("print", |_signal| { println!("New Output!"); })?
564///				.enable()?;
565///
566///		Ok(())
567/// }
568/// ```
569#[derive(Debug)]
570pub struct SignalHandle {
571    signal: Signal,
572    sender: Sender<Action>,
573}
574
575/* Convenient Type Alias */
576type SignalResult<'a> = Result<&'a mut SignalHandle, Error>;
577
578impl SignalHandle {
579    /// Registers a callback with the interrupt handler for the associated
580    /// Signal. If you call register with the same name it will replace the
581    /// previous callback.
582    ///
583    /// # Example
584    /// ```
585    /// use addy::{Signal, SIGWINCH};
586    ///
587    /// fn my_func(signal: Signal) {
588    /// 	/* Does a thing */
589    /// }
590    ///
591    /// fn main() -> Result<(), addy::Error> {
592    /// 	addy::mediate(SIGWINCH)
593    ///				.register("print", |_signal| { println!("Screen Resized!"); })?
594    ///				.register("my_func", my_func)?
595    ///				.enable()?;
596    ///
597    ///		Ok(())
598    /// }
599    /// ```
600    pub fn register<'a, A, F>(&'a mut self, name: A, cb: F) -> SignalResult
601    where
602        A: AsRef<str>,
603        F: Fn(Signal) -> () + Send + 'static,
604    {
605        /* Box the Callback */
606        let cb = CBP(Box::new(cb));
607        let name = String::from(name.as_ref());
608        self.sender
609            .send(Action::Register(self.signal, name, cb))
610            .map_err(|_| Error::CallFailed)?;
611        Ok(self)
612    }
613
614    /// Removes a named callback from the associated Signal. If no callback with
615    /// that name exists, it does nothing.
616    ///
617    /// # Example
618    /// ```
619    /// use addy::{Signal, SIGWINCH};
620    ///
621    /// fn my_func(signal: Signal) {
622    /// 	/* Does a thing */
623    /// }
624    ///
625    /// fn main() -> Result<(), addy::Error> {
626    /// 	addy::mediate(SIGWINCH)
627    ///				.register("print", |_signal| { println!("Screen Resized!"); })?
628    ///				.register("my_func", my_func)?
629    ///				.enable()?;
630    ///
631    ///		//-- Later --//
632    ///
633    ///		// Stop calling "print" when the process receives a SIGWINCH signal
634    /// 	addy::mediate(SIGWINCH).remove("print")?;
635    ///
636    ///		Ok(())
637    /// }
638    /// ```
639    pub fn remove<'a, A>(&'a mut self, name: A) -> SignalResult
640    where
641        A: AsRef<str>,
642    {
643        let name = String::from(name.as_ref());
644        self.sender
645            .send(Action::Remove(self.signal, name))
646            .map_err(|_| Error::CallFailed)?;
647        Ok(self)
648    }
649
650    /// Removes a all callbacks from the associated Signal. Functionally similar
651    /// to calling .ignore() except you don't need to call .enable() if you add
652    /// new callbacks later.
653    ///
654    /// # Example
655    /// ```
656    /// use addy::{Signal, SIGWINCH};
657    ///
658    /// fn my_func(signal: Signal) {
659    /// 	/* Does a thing */
660    /// }
661    ///
662    /// fn main() -> Result<(), addy::Error> {
663    /// 	addy::mediate(SIGWINCH)
664    ///				.register("print", |_signal| { println!("Screen Resized!"); })?
665    ///				.register("my_func", my_func)?
666    ///				.enable()?;
667    ///
668    ///		//-- Later --//
669    ///
670    ///		// Capture the signal, but stop calling anything
671    /// 	addy::mediate(SIGWINCH)
672    /// 			.clear()?
673    ///				.register("solo_callback", |_signal| { println!("ALONE!"); })?;
674    ///
675    ///		Ok(())
676    /// }
677    /// ```
678    pub fn clear<'a>(&'a mut self) -> SignalResult {
679        self.sender
680            .send(Action::Clear(self.signal))
681            .map_err(|_| Error::CallFailed)?;
682        Ok(self)
683    }
684
685    /// Removes a all callbacks from the associated Signal and resets the
686    /// interrupt handler to the default behavior. Funcationally the same as
687    /// calling .clear() and .default().
688    ///
689    /// You will need to call .enable() again after re-registering callbacks.
690    ///
691    /// # Example
692    /// ```
693    /// use addy::SIGWINCH;
694    ///
695    /// fn main() -> Result<(), addy::Error> {
696    /// 	addy::mediate(SIGWINCH)
697    ///				.register("print", |_signal| { println!("Screen Resized!"); })?
698    ///				.enable()?;
699    ///
700    ///		//-- Later --//
701    ///
702    ///		// Stop capturing the signal
703    /// 	addy::mediate(SIGWINCH).release()?;
704    ///  
705    /// 	//-- Later Still --//
706    ///
707    /// 	// Start catpuring again
708    ///		addy::mediate(SIGWINCH)
709    ///				.register("new", |_signal| { println!("New callback!"); })?
710    ///				.enable()?;
711    ///
712    ///		Ok(())
713    /// }
714    /// ```
715    pub fn release<'a>(&'a mut self) -> SignalResult {
716        self.sender
717            .send(Action::Release(self.signal))
718            .map_err(|_| Error::CallFailed)?;
719        Ok(self)
720    }
721
722    /// Tells the process to ignore this interrupt. Keeps all your callbacks.
723    /// Calling .resume() will re-enable them.
724    ///
725    /// # Example
726    /// ```
727    /// use addy::SIGWINCH;
728    ///
729    /// fn main() -> Result<(), addy::Error> {
730    /// 	addy::mediate(SIGWINCH)
731    ///				.register("print", |_signal| { println!("Screen Resized!"); })?
732    ///				.enable()?;
733    ///
734    ///		//-- Later --//
735    ///
736    ///		// Ignore the signal
737    /// 	addy::mediate(SIGWINCH).ignore()?;
738    ///
739    /// 	//-- Later Still --//
740    ///
741    /// 	// Start catpuring again
742    ///		addy::mediate(SIGWINCH).resume()?;
743    ///
744    ///		Ok(())
745    /// }
746    /// ```
747    pub fn ignore<'a>(&'a mut self) -> SignalResult {
748        self.sender
749            .send(Action::Ignore(self.signal))
750            .map_err(|_| Error::CallFailed)?;
751        Ok(self)
752    }
753
754    /// Restore the interrupt handler to the system default. Not all interrupts
755    /// have a default, and some interrupts default is to be ignored. Keeps all
756    /// your callbacks. Calling .resume() will re-enable them.
757    ///
758    /// # Example
759    /// ```
760    /// use addy::SIGINT;
761    ///
762    /// fn main() -> Result<(), addy::Error> {
763    /// 	addy::mediate(SIGINT)
764    ///				.register("print", |_signal| { println!("Interrupted!"); })?
765    ///				.enable()?;
766    ///
767    ///		//-- Later --//
768    ///
769    ///		// Set the signal to its default
770    /// 	addy::mediate(SIGINT).default()?;
771    ///
772    /// 	//-- Later Still --//
773    ///
774    /// 	// Start catpuring again
775    ///		addy::mediate(SIGINT).resume()?;
776    ///
777    ///		Ok(())
778    /// }
779    /// ```
780    pub fn default<'a>(&'a mut self) -> SignalResult {
781        self.sender
782            .send(Action::Default(self.signal))
783            .map_err(|_| Error::CallFailed)?;
784        Ok(self)
785    }
786
787    /// Resumes capturing the interrupt and calling any associated callbacks.
788    /// Most often used after a call to .ignore() and .default().
789    ///
790    /// Alias of .enable()
791    ///
792    /// # Example
793    /// ```
794    /// use addy::SIGINT;
795    ///
796    /// fn main() -> Result<(), addy::Error> {
797    /// 	addy::mediate(SIGINT)
798    ///				.register("print", |_signal| { println!("Interrupted!"); })?
799    ///				.enable()?;
800    ///
801    ///		//-- Later --//
802    ///
803    ///		// Set the signal to its default
804    /// 	addy::mediate(SIGINT).default()?;
805    ///
806    /// 	//-- Later Still --//
807    ///
808    ///		// Start catpuring and printing "Interrupted!" again
809    ///		addy::mediate(SIGINT).resume()?;
810    ///
811    ///		Ok(())
812    /// }
813    /// ```
814    pub fn resume<'a>(&'a mut self) -> SignalResult {
815        self.sender
816            .send(Action::Resume(self.signal))
817            .map_err(|_| Error::CallFailed)?;
818        Ok(self)
819    }
820
821    /// Begins capturing the interrupt and calling any associated callbacks.
822    /// Most often used after a calls .register()
823    ///
824    /// Alias of .resume()
825    ///
826    /// # Example
827    /// ```
828    /// use addy::SIGINT;
829    ///
830    /// fn main() -> Result<(), addy::Error> {
831    /// 	addy::mediate(SIGINT)
832    ///				.register("print", |_signal| { println!("Interrupted!"); })?
833    ///				.enable()?;
834    ///		Ok(())
835    /// }
836    /// ```
837    pub fn enable<'a>(&'a mut self) -> SignalResult {
838        self.sender
839            .send(Action::Resume(self.signal))
840            .map_err(|_| Error::CallFailed)?;
841        Ok(self)
842    }
843}
844
845/**************************************
846 * SETUP EVENT LOOP & MPSC CHANNEL *
847 **************************************/
848/* This is the thread that the different interrupt handlers send messages to.
849 * when they occur. They message what they want done and this thread executes it.
850*/
851
852/* This closure can only be called at most ONCE - allows us to ensure the Event
853 * Loop is set up a maximum of one time. This also means that if the MPSC
854 * channel ever fails we can't recover from it.
855*/
856static SETUP: Once = Once::new();
857
858/* FUTURE: Consider removing this to remove the dependency on lazy_static!()
859 * This gets set up ONCE and then only read from. The downside is more
860 * unsafe {} blocks :<
861 *
862 * Currently SENDER is only accessed in one place, that can only be run one at
863 * a time (i.e. in an interrupt) and copies of SAFE_SENDER can be made from
864 * any thread at any time. Still... it's read only...
865*/
866lazy_static! {
867    /* MPSC channel used by interrupts to communicate to the Event Loop. This
868     * stores a global copy of a Sender that can be cloned and given to the
869     * various interrupt handlers as they are created.
870    */
871    static ref SAFE_SENDER: Mutex<Option<Sender<Action>>> = {
872        Mutex::new(None)
873    };
874}
875
876/* C FFI MESSAGE PASSER
877 *
878 * Copy of a sender to the Event Loop. It is only setup ONCE on the first
879 * addy::mediate() call. The setup always occurs before it is READ from as it is
880 * set before any handler is registered (the only place that attempts to read
881 * from this static global).
882*/
883static mut SENDER: Option<Sender<Action>> = None;
884
885/* This is the initial Addy setup. It sets up the Event Loop and the MPCS
886 * channel. Setup occurs on the first call of addy::mediate(Signal).
887*/
888
889type NameToCallback = FnvHashMap<String, CBP>;
890type SignalToCallbacks<T> = FnvHashMap<Signal, T>;
891fn setup() {
892    /* Only setup the Event Loop once */
893    SETUP.call_once(|| {
894        // we may need to block on "completed" to make sure this is completed
895        // Setup an async MPSC channel - the receiver will be the Event Loop
896        let (sender, receiver) = mpsc::channel::<Action>();
897
898        /* Save a copy of a sender to a global variable so it can be
899         * clone()'d and handed off to future singal handlers structs.
900        	*/
901        {
902            let mut guard = SAFE_SENDER.lock().unwrap();
903            guard.replace(sender.clone());
904        }
905
906        /* Save a copy of the sender in an global static mut Option
907         *
908         * This is SAFE because this is only called ONCE and the only other
909         * place this is accessed is in fn  c_handler() which cannot be called
910         * before this setup is run. In addition, only one interrupt handler can
911         * be running at a time, which is why this convolution is necessary.
912        	*/
913        unsafe {
914            SENDER.replace(sender.clone());
915        }
916
917        /**************
918         * EVENT LOOP *
919         **************/
920
921        /* Spawn the Event Loop thread, pass the receiver to it. */
922        thread::spawn(move || {
923            /* Create a map from Signal -> Map<Name, Closure> */
924            let nsig = usize::try_from(NUM_SIGNALS).unwrap(); // i32(32) - constant we control :)
925            let mut handlers = SignalToCallbacks::<NameToCallback>::with_capacity_and_hasher(
926                nsig,
927                Default::default(),
928            );
929
930            /* Stores if we need to re-establish fn c_handler() as the interrupt
931             * handler. e.g. if the user called .ignore() and then .resume()
932            	*/
933            let mut active: [bool; NUM_SIGNALS as usize] = [false; 32];
934
935            /*************
936             * CONSTANTS *
937             *************/
938            /* SigAction Structs to represent the SIG_DFL, SIG_IGN and custom
939             * handler. These are passed to libc::sigaction(...) to tell it what
940             * to do when a signal is called. They tell it to perform the
941             * default action, ignore the signal or run the list of user
942             * registered callbacks respectively.
943             */
944
945            /* Have to create a mask for the structs that enables all singals */
946            let mut sigset = std::mem::MaybeUninit::uninit();
947            let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
948            let sigset = unsafe { sigset.assume_init() };
949
950            #[allow(non_snake_case)]
951            let SA_DEFAULT: libc::sigaction = libc::sigaction {
952                sa_sigaction: libc::SIG_DFL,
953                sa_mask: sigset,
954                sa_flags: libc::SA_SIGINFO,
955                #[cfg(target_os = "linux")]
956                sa_restorer: None,
957            };
958
959            #[allow(non_snake_case)]
960            let SA_IGNORE: libc::sigaction = libc::sigaction {
961                sa_sigaction: libc::SIG_IGN,
962                sa_mask: sigset,
963                sa_flags: libc::SA_SIGINFO,
964                #[cfg(target_os = "linux")]
965                sa_restorer: None,
966            };
967
968            /* Q: Why isn't this a constant?
969             * A: Converting function pointers to integers in a constant is
970             * unstable. (Yes I tried the various workarounds)
971             *
972             * Link: https://github.com/rust-lang/rust/issues/51910
973             */
974            #[allow(non_snake_case)]
975            let SA_CALLBACK: libc::sigaction = libc::sigaction {
976                sa_sigaction: c_handler as libc::sighandler_t,
977                sa_mask: sigset,
978                sa_flags: libc::SA_SIGINFO,
979                #[cfg(target_os = "linux")]
980                sa_restorer: None,
981            };
982
983            /***************************************
984             * HELPER FUNCTIONS TO KEEP THINGS DRY *
985             ***************************************/
986            /* Switched to helper closures because some architectures need
987             * a proper sa_mask generated to compile.
988             */
989
990            /* Tells the process to ignore the interrupt */
991            let ignore = move |signal: Signal| unsafe {
992                libc::sigaction(signal as libc::c_int, &SA_IGNORE, std::ptr::null_mut());
993            };
994            /* Sets the interrupt handler to the default value */
995            let default = move |signal: Signal| unsafe {
996                libc::sigaction(signal as libc::c_int, &SA_DEFAULT, std::ptr::null_mut());
997            };
998            /* Trys to convert a Signal to a USize to index into active[] */
999            fn index(signal: Signal) -> usize {
1000                usize::try_from(signal as libc::c_int).unwrap()
1001            }
1002            /* Resets all signals to their default behaviour. Does not clear out
1003             * registered handlers.
1004            	*/
1005            let set_all_to_default = || {
1006                for signal in Signal::iterator() {
1007                    default(signal);
1008                }
1009            };
1010
1011            /*********
1012             * PANIC *
1013             *********/
1014
1015            /* If this thread panics for any reason, set all signals to the
1016             * default behavior.
1017            	*/
1018            let _ = std::panic::catch_unwind(|| {
1019                set_all_to_default();
1020            });
1021
1022            /**************
1023             * EVENT LOOP *
1024             **************/
1025
1026            /* Returns None when the channel is closed. */
1027            let mut messages = receiver.iter();
1028            while let Some(action) = messages.next() {
1029                match action {
1030                    Action::Call(signal) => {
1031                        /* Get the map of callbacks for this signal */
1032                        if let Some(callbacks) = handlers.get(&signal) {
1033                            /* Call each callback */
1034                            let callbacks = callbacks.iter();
1035                            for (_, cb) in callbacks {
1036                                cb.0(signal);
1037                            }
1038                        }
1039                    }
1040                    Action::Register(signal, name, cb) => {
1041                        /* Get the map of callbacks for this signal */
1042                        let callbacks = handlers.entry(signal).or_default();
1043                        callbacks.insert(name, cb);
1044                    }
1045                    Action::Remove(signal, name) => {
1046                        /* Get the map of callbacks for this signal */
1047                        if let Some(callbacks) = handlers.get_mut(&signal) {
1048                            callbacks.remove(&name);
1049                        }
1050                    }
1051                    Action::Clear(signal) => {
1052                        handlers.remove(&signal);
1053                    }
1054                    Action::Ignore(signal) => {
1055                        ignore(signal);
1056                        active[index(signal)] = false;
1057                    }
1058                    Action::Default(signal) => {
1059                        default(signal);
1060                        active[index(signal)] = false;
1061                    }
1062                    Action::Release(signal) => {
1063                        /* Clear the callback map */
1064                        handlers.remove(&signal);
1065
1066                        /* Set the handler back to the defaults */
1067                        default(signal);
1068                        active[index(signal)] = false;
1069                    }
1070                    Action::Resume(signal) => {
1071                        /* Check to see if it's already setup up */
1072                        if !active[index(signal)] {
1073                            unsafe {
1074                                /* SA_CALLBACK is a static sigaction struct that
1075                                 * points to c_handler(...)
1076                                	*/
1077                                libc::sigaction(
1078                                    signal as libc::c_int,
1079                                    &SA_CALLBACK,
1080                                    std::ptr::null_mut(),
1081                                );
1082                            }
1083                            active[index(signal)] = true;
1084                        }
1085                    }
1086                }
1087            } // </Event Loop>
1088
1089            /* If the thread closes - set all the singals back to their default
1090             * behavior and remove all callbacks.
1091             */
1092            set_all_to_default();
1093        }); // </Thread>
1094    }); // </Once>
1095
1096    /* There's a chance that the ONCE call actually initialized something else
1097     * and that we're not ready so we spin until we are. Probably not necessary.
1098     *
1099     * Apparently it's only available on nightly, but is merged in and will be
1100     * stable shortly. See link below for detail:
1101     *
1102     * Link: https://github.com/rust-lang/rust/issues/54890
1103     */
1104    #[cfg(feature = "nightly")]
1105    while !SETUP.is_completed() { /*-- ᓚᘏᗢ --*/ }
1106}
1107
1108/***********
1109 * MEDIATE *
1110 ***********/
1111
1112/* If this is the FIRST time new has been called, for _any_ Signal it
1113 * will set up the Event Loop thread and MPCS handlers as well.
1114*/
1115/// Use this to get a SignalHandle representing a interrupt specified by Signal.
1116///
1117/// # Example
1118/// ```no_run
1119/// use addy::SIGWINCH;
1120///	use std::io::{Read, stdin};
1121///
1122/// fn main() -> Result<(), addy::Error> {
1123/// 	/* SIGWINCH is a POSIX interrupt signal */
1124/// 	addy::mediate(SIGWINCH)
1125///				.register("resized", |_signal| { println!("Screen Resized!"); })?
1126///				.enable()?;
1127///
1128///		/* Block so the program doesn't exit immediately
1129/// 	 * Try resizing your terminal window :)
1130/// 	*/
1131///		let mut buffer = [0; 1];
1132///    	loop {
1133///        stdin().read(&mut buffer);
1134///   	}
1135///
1136/// 	Ok(())
1137/// }
1138/// ```
1139pub fn mediate<S: Into<Signal>>(signal: S) -> SignalHandle {
1140    let signal = signal.into();
1141
1142    /* Performs the initial setup for all handlers - only called ONCE */
1143    setup();
1144
1145    /* Create a clone() of the Sender so we can pass messages to the Event
1146     * Loop from the returned struct.
1147    	*/
1148    let sender;
1149    {
1150        let guard = SAFE_SENDER.lock().unwrap();
1151        sender = guard.as_ref().unwrap().clone();
1152    }
1153
1154    SignalHandle { signal, sender }
1155}
1156
1157/* Alternative, arcane, profane function aliases for addy::mediate(...) */
1158#[doc(hidden)]
1159pub fn medicate(signal: Signal) {
1160    mediate(signal);
1161}
1162#[doc(hidden)]
1163pub fn intercept(signal: Signal) {
1164    mediate(signal);
1165}