1 //! Interface for the `signalfd` syscall.
2 //!
3 //! # Signal discarding
4 //! When a signal can't be delivered to a process (or thread), it will become a pending signal.
5 //! Failure to deliver could happen if the signal is blocked by every thread in the process or if
6 //! the signal handler is still handling a previous signal.
7 //!
8 //! If a signal is sent to a process (or thread) that already has a pending signal of the same
9 //! type, it will be discarded. This means that if signals of the same type are received faster than
10 //! they are processed, some of those signals will be dropped. Because of this limitation,
11 //! `signalfd` in itself cannot be used for reliable communication between processes or threads.
12 //!
13 //! Once the signal is unblocked, or the signal handler is finished, and a signal is still pending
14 //! (ie. not consumed from a signalfd) it will be delivered to the signal handler.
15 //!
16 //! Please note that signal discarding is not specific to `signalfd`, but also happens with regular
17 //! signal handlers.
18 use crate::errno::Errno;
19 pub use crate::sys::signal::{self, SigSet};
20 use crate::Result;
21 pub use libc::signalfd_siginfo as siginfo;
22 
23 use std::mem;
24 use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
25 
26 libc_bitflags! {
27     pub struct SfdFlags: libc::c_int {
28         SFD_NONBLOCK;
29         SFD_CLOEXEC;
30     }
31 }
32 
33 #[deprecated(since = "0.23.0", note = "use mem::size_of::<siginfo>() instead")]
34 pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>();
35 
36 /// Creates a new file descriptor for reading signals.
37 ///
38 /// **Important:** please read the module level documentation about signal discarding before using
39 /// this function!
40 ///
41 /// The `mask` parameter specifies the set of signals that can be accepted via this file descriptor.
42 ///
43 /// A signal must be blocked on every thread in a process, otherwise it won't be visible from
44 /// signalfd (the default handler will be invoked instead).
45 ///
46 /// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html)
47 #[deprecated(since = "0.27.0", note = "Use SignalFd instead")]
signalfd<F: AsFd>( fd: Option<F>, mask: &SigSet, flags: SfdFlags, ) -> Result<OwnedFd>48 pub fn signalfd<F: AsFd>(
49     fd: Option<F>,
50     mask: &SigSet,
51     flags: SfdFlags,
52 ) -> Result<OwnedFd> {
53     _signalfd(fd, mask, flags)
54 }
55 
_signalfd<F: AsFd>( fd: Option<F>, mask: &SigSet, flags: SfdFlags, ) -> Result<OwnedFd>56 fn _signalfd<F: AsFd>(
57     fd: Option<F>,
58     mask: &SigSet,
59     flags: SfdFlags,
60 ) -> Result<OwnedFd> {
61     let raw_fd = fd.map_or(-1, |x| x.as_fd().as_raw_fd());
62     unsafe {
63         Errno::result(libc::signalfd(raw_fd, mask.as_ref(), flags.bits()))
64             .map(|raw_fd| FromRawFd::from_raw_fd(raw_fd))
65     }
66 }
67 
68 /// A helper struct for creating, reading and closing a `signalfd` instance.
69 ///
70 /// **Important:** please read the module level documentation about signal discarding before using
71 /// this struct!
72 ///
73 /// # Examples
74 ///
75 /// ```
76 /// # use nix::sys::signalfd::*;
77 /// // Set the thread to block the SIGUSR1 signal, otherwise the default handler will be used
78 /// let mut mask = SigSet::empty();
79 /// mask.add(signal::SIGUSR1);
80 /// mask.thread_block().unwrap();
81 ///
82 /// // Signals are queued up on the file descriptor
83 /// let mut sfd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
84 ///
85 /// match sfd.read_signal() {
86 ///     // we caught a signal
87 ///     Ok(Some(sig)) => (),
88 ///     // there were no signals waiting (only happens when the SFD_NONBLOCK flag is set,
89 ///     // otherwise the read_signal call blocks)
90 ///     Ok(None) => (),
91 ///     Err(err) => (), // some error happend
92 /// }
93 /// ```
94 #[derive(Debug)]
95 pub struct SignalFd(OwnedFd);
96 
97 impl SignalFd {
new(mask: &SigSet) -> Result<SignalFd>98     pub fn new(mask: &SigSet) -> Result<SignalFd> {
99         Self::with_flags(mask, SfdFlags::empty())
100     }
101 
with_flags(mask: &SigSet, flags: SfdFlags) -> Result<SignalFd>102     pub fn with_flags(mask: &SigSet, flags: SfdFlags) -> Result<SignalFd> {
103         let fd = _signalfd(None::<OwnedFd>, mask, flags)?;
104 
105         Ok(SignalFd(fd))
106     }
107 
set_mask(&mut self, mask: &SigSet) -> Result<()>108     pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> {
109         self.update(mask, SfdFlags::empty())
110     }
111 
read_signal(&mut self) -> Result<Option<siginfo>>112     pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
113         let mut buffer = mem::MaybeUninit::<siginfo>::uninit();
114 
115         let size = mem::size_of_val(&buffer);
116         let res = Errno::result(unsafe {
117             libc::read(self.0.as_raw_fd(), buffer.as_mut_ptr().cast(), size)
118         })
119         .map(|r| r as usize);
120         match res {
121             Ok(x) if x == size => Ok(Some(unsafe { buffer.assume_init() })),
122             Ok(_) => unreachable!("partial read on signalfd"),
123             Err(Errno::EAGAIN) => Ok(None),
124             Err(error) => Err(error),
125         }
126     }
127 
update(&self, mask: &SigSet, flags: SfdFlags) -> Result<()>128     fn update(&self, mask: &SigSet, flags: SfdFlags) -> Result<()> {
129         let raw_fd = self.0.as_raw_fd();
130         unsafe {
131             Errno::result(libc::signalfd(raw_fd, mask.as_ref(), flags.bits()))
132                 .map(drop)
133         }
134     }
135 }
136 
137 impl AsFd for SignalFd {
as_fd(&self) -> BorrowedFd138     fn as_fd(&self) -> BorrowedFd {
139         self.0.as_fd()
140     }
141 }
142 impl AsRawFd for SignalFd {
as_raw_fd(&self) -> RawFd143     fn as_raw_fd(&self) -> RawFd {
144         self.0.as_raw_fd()
145     }
146 }
147 
148 impl Iterator for SignalFd {
149     type Item = siginfo;
150 
next(&mut self) -> Option<Self::Item>151     fn next(&mut self) -> Option<Self::Item> {
152         match self.read_signal() {
153             Ok(Some(sig)) => Some(sig),
154             Ok(None) | Err(_) => None,
155         }
156     }
157 }
158