signal_stack/lib.rs
1//! # signal-stack
2//!
3//! Low-level library for installing signal handlers. Signal handlers are
4//! modelled as a stack: when a signal is raised, the stack is traversed
5//! from top to bottom, and each signal handler is called in turn.
6//!
7//! A signal handler can return `true` to indicate that the signal was
8//! handled. In this case, no further handlers will be called. If no
9//! signal handler returns `true` then the default behaviour for that
10//! signal will occur.
11
12#![deny(missing_docs)]
13
14use std::sync::Arc;
15
16use libc::c_int;
17
18mod backend;
19mod signal_safe;
20mod stack;
21
22pub use stack::Handler;
23
24/// A type may implement this trait to indicate that it can be converted
25/// into an async-signal-safe function. ie. one that is safe to call from
26/// a signal handler.
27pub unsafe trait SafeHandler: Into<Arc<dyn Handler>> {}
28
29/// This is the primary interface to the crate. When this guard is constructed
30/// a new signal handler for one or more signals is pushed onto the top of the
31/// stack.
32///
33/// When it is dropped, the signal handler will be removed from the stack.
34/// Signal handlers can be removed at any time, it need not be in reverse
35/// order, although that would typically be the case.
36#[derive(Debug)]
37pub struct SignalHandlerGuard<'a> {
38 signums: &'a [c_int],
39 handler_id: stack::HandlerId,
40}
41
42impl<'a> SignalHandlerGuard<'a> {
43 /// Add a new signal handler.
44 ///
45 /// # Safety
46 /// The handler function *must* be `async-signal-safe`, which places severe
47 /// restrictions on what the function may do.
48 ///
49 /// A non-exhaustive list of things that are not allowed:
50 /// - Allocating or freeing memory.
51 /// - Locking or unlocking mutexes or other kinds of concurrency primitive,
52 /// with the exception of posting to a `libc` semaphore.
53 /// - Calling a function which is not itself marked as async-signal-safe.
54 /// - Performing any kind of blocking I/O.
55 pub unsafe fn new_unsafe(signums: &'a [c_int], handler: Arc<dyn Handler>) -> Self {
56 Self {
57 signums,
58 handler_id: stack::add_handler(signums, handler),
59 }
60 }
61
62 /// Safely construct a signal guard from a function known statically to be
63 /// async-signal-safe.
64 pub fn new<H: SafeHandler>(signums: &'a [c_int], handler: H) -> Self {
65 unsafe { Self::new_unsafe(signums, handler.into()) }
66 }
67
68 /// Forget this signal guard: the handler will remain attached for the lifetime
69 /// of the program.
70 pub fn forget(mut self) {
71 self.signums = &[];
72 }
73}
74
75impl<'a> Drop for SignalHandlerGuard<'a> {
76 fn drop(&mut self) {
77 unsafe {
78 stack::remove_handler(self.signums, &self.handler_id);
79 }
80 }
81}