devela/sys/os/linux/structs/sigaction.rs
1// devela::sys::os::linux::structs::sigaction
2
3#![cfg_attr(not(feature = "unsafe_syscall"), allow(dead_code))]
4
5/// Represents the [`sigaction`] structure from libc.
6/// Examine and change a signal action.
7///
8/// [`sigaction`]: https://man7.org/linux/man-pages/man2/sigaction.2.html
9#[derive(Debug)]
10#[repr(C)]
11pub struct LinuxSigaction {
12 /// A pointer to a signal handling function.
13 ///
14 /// This function receives the signal number as its only argument.
15 pub sa_handler: extern "C" fn(i32),
16
17 /// A set of flags which modify the behavior of the signal.
18 pub sa_flags: usize,
19
20 /// A legacy field that is not used on modern Linux systems, but must be
21 /// filled in for compatibility
22 pub sa_restorer: Option<extern "C" fn()>,
23
24 /// A mask of signals that should be blocked.
25 pub sa_mask: LinuxSigset,
26}
27
28impl LinuxSigaction {
29 /// Retuns a new `LinuxSigation`.
30 #[must_use]
31 pub fn new(handler: extern "C" fn(i32), flags: usize, mask: LinuxSigset) -> Self {
32 Self {
33 sa_handler: handler,
34 sa_flags: flags,
35 sa_restorer: None,
36 sa_mask: mask,
37 }
38 }
39}
40
41/// [`sa_handler`][Self::sa_handler] field constants.
42impl LinuxSigaction {
43 /// The default signal handling.
44 pub const SIG_DFL: isize = 0;
45
46 /// Ignore this signal.
47 pub const SIG_IGN: isize = 1;
48
49 // /// Error return from signal.
50 // pub const SIG_ERR: isize = -1;
51}
52
53/// A set of signals.
54#[repr(C)]
55#[derive(Debug, Default, Clone, Copy)]
56pub struct LinuxSigset {
57 /// An array of signals.
58 ///
59 /// Its lenght is calculated from the number of signals divided by the bits of a usize.
60 pub sig: [usize; Self::LEN],
61}
62impl LinuxSigset {
63 const BITS_PER_USIZE: usize = usize::BITS as usize;
64 // The hardcoded number of system signals defined in `LINUX_SIGNAL`.
65 const NSIG: usize = 36;
66 // The size of the array is the number of signals divided by the bits of an usize.
67 const LEN: usize = { Self::NSIG.div_ceil(Self::BITS_PER_USIZE) };
68
69 /// Returns the size in bytes of `LinuxSigset`.
70 #[must_use]
71 pub const fn size() -> usize {
72 core::mem::size_of::<Self>()
73 }
74}
75impl LinuxSigset {
76 /// Sets the bit corresponding to a `signal` in the `sig` array.
77 ///
78 /// # Arguments
79 /// * `signum` - The number of the signal. This should be between 1 and `NSIG`.
80 ///
81 /// # Panics
82 /// Panics if `signum` < 1 or > 36.
83 pub fn set_signal(&mut self, signal: i32) {
84 let signal = signal as usize;
85 assert![(1..=Self::NSIG).contains(&signal)];
86
87 // Subtract 1 from the signal number because signal numbers start from 1
88 // but array indices start from 0
89 let signal_index = (signal - 1) / Self::BITS_PER_USIZE;
90 let bit_position = (signal - 1) % Self::BITS_PER_USIZE;
91 self.sig[signal_index] |= 1 << bit_position;
92 }
93}