| 1 | //! An iterator over incoming signals. |
| 2 | //! |
| 3 | //! This provides a higher abstraction over the signals, providing |
| 4 | //! the [`SignalsInfo`] structure which is able to iterate over the |
| 5 | //! incoming signals. The structure is parametrized by an |
| 6 | //! [`Exfiltrator`][self::exfiltrator::Exfiltrator], which specifies what information is returned |
| 7 | //! for each delivered signal. Note that some exfiltrators are behind a feature flag. |
| 8 | //! |
| 9 | //! The [`Signals`] is a type alias for the common case when it is enough to get the signal number. |
| 10 | //! |
| 11 | //! This module (and everything in it) is turned by the `iterator` feature. It is **on** by |
| 12 | //! default, the possibility to turn off is mostly possible for very special purposes (compiling on |
| 13 | //! `<rustc-1.36`, minimizing the amount of code compiled, …). In a sense, this is the highest |
| 14 | //! level abstraction of the crate and the API expected to be used by most of the people. |
| 15 | //! |
| 16 | //! # Examples |
| 17 | //! |
| 18 | //! ```rust |
| 19 | //! extern crate libc; |
| 20 | //! extern crate signal_hook; |
| 21 | //! |
| 22 | //! use std::io::Error; |
| 23 | //! |
| 24 | //! use signal_hook::consts::signal::*; |
| 25 | //! use signal_hook::iterator::Signals; |
| 26 | //! |
| 27 | //! fn main() -> Result<(), Error> { |
| 28 | //! let mut signals = Signals::new(&[ |
| 29 | //! SIGHUP, |
| 30 | //! SIGTERM, |
| 31 | //! SIGINT, |
| 32 | //! SIGQUIT, |
| 33 | //! # SIGUSR1, |
| 34 | //! ])?; |
| 35 | //! # // A trick to terminate the example when run as doc-test. Not part of the real code. |
| 36 | //! # signal_hook::low_level::raise(SIGUSR1).unwrap(); |
| 37 | //! 'outer: loop { |
| 38 | //! // Pick up signals that arrived since last time |
| 39 | //! for signal in signals.pending() { |
| 40 | //! match signal as libc::c_int { |
| 41 | //! SIGHUP => { |
| 42 | //! // Reload configuration |
| 43 | //! // Reopen the log file |
| 44 | //! } |
| 45 | //! SIGTERM | SIGINT | SIGQUIT => { |
| 46 | //! break 'outer; |
| 47 | //! }, |
| 48 | //! # SIGUSR1 => return Ok(()), |
| 49 | //! _ => unreachable!(), |
| 50 | //! } |
| 51 | //! } |
| 52 | //! // Do some bit of work ‒ something with upper limit on waiting, so we don't block |
| 53 | //! // forever with a SIGTERM already waiting. |
| 54 | //! } |
| 55 | //! println!("Terminating. Bye bye" ); |
| 56 | //! Ok(()) |
| 57 | //! } |
| 58 | //! ``` |
| 59 | |
| 60 | pub mod backend; |
| 61 | pub mod exfiltrator; |
| 62 | |
| 63 | use std::borrow::Borrow; |
| 64 | use std::fmt::{Debug, Formatter, Result as FmtResult}; |
| 65 | use std::io::{Error, ErrorKind, Read}; |
| 66 | use std::os::unix::net::UnixStream; |
| 67 | |
| 68 | use libc::{self, c_int}; |
| 69 | |
| 70 | pub use self::backend::{Handle, Pending}; |
| 71 | use self::backend::{PollResult, RefSignalIterator, SignalDelivery}; |
| 72 | use self::exfiltrator::{Exfiltrator, SignalOnly}; |
| 73 | |
| 74 | /// The main structure of the module, representing interest in some signals. |
| 75 | /// |
| 76 | /// Unlike the helpers in other modules, this registers the signals when created and unregisters |
| 77 | /// them on drop. It provides the pending signals during its lifetime, either in batches or as an |
| 78 | /// infinite iterator. |
| 79 | /// |
| 80 | /// Most users will want to use it through the [`Signals`] type alias for simplicity. |
| 81 | /// |
| 82 | /// # Multiple threads |
| 83 | /// |
| 84 | /// Instances of this struct can be [sent][std::marker::Send] to other threads. In a multithreaded |
| 85 | /// application this can be used to dedicate a separate thread for signal handling. In this case |
| 86 | /// you should get a [`Handle`] using the [`handle`][Signals::handle] method before sending the |
| 87 | /// `Signals` instance to a background thread. With the handle you will be able to shut down the |
| 88 | /// background thread later, or to operatively add more signals. |
| 89 | /// |
| 90 | /// The controller handle can be shared between as many threads as you like using its |
| 91 | /// [`clone`][Handle::clone] method. |
| 92 | /// |
| 93 | /// # Exfiltrators |
| 94 | /// |
| 95 | /// The [`SignalOnly]` provides only the signal number. There are further exfiltrators available in |
| 96 | /// the [`exfiltrator`] module. Note that some of them are behind feature flags that need to be |
| 97 | /// enabled. |
| 98 | /// |
| 99 | /// # Examples |
| 100 | /// |
| 101 | /// ```rust |
| 102 | /// # extern crate signal_hook; |
| 103 | /// # |
| 104 | /// # use std::io::Error; |
| 105 | /// # use std::thread; |
| 106 | /// use signal_hook::consts::signal::*; |
| 107 | /// use signal_hook::iterator::Signals; |
| 108 | /// |
| 109 | /// # |
| 110 | /// # fn main() -> Result<(), Error> { |
| 111 | /// let mut signals = Signals::new(&[SIGUSR1, SIGUSR2])?; |
| 112 | /// let handle = signals.handle(); |
| 113 | /// let thread = thread::spawn(move || { |
| 114 | /// for signal in &mut signals { |
| 115 | /// match signal { |
| 116 | /// SIGUSR1 => {}, |
| 117 | /// SIGUSR2 => {}, |
| 118 | /// _ => unreachable!(), |
| 119 | /// } |
| 120 | /// } |
| 121 | /// }); |
| 122 | /// |
| 123 | /// // Some time later... |
| 124 | /// handle.close(); |
| 125 | /// thread.join().unwrap(); |
| 126 | /// # Ok(()) |
| 127 | /// # } |
| 128 | /// ``` |
| 129 | pub struct SignalsInfo<E: Exfiltrator = SignalOnly>(SignalDelivery<UnixStream, E>); |
| 130 | |
| 131 | impl<E: Exfiltrator> SignalsInfo<E> { |
| 132 | /// Creates the `Signals` structure. |
| 133 | /// |
| 134 | /// This registers all the signals listed. The same restrictions (panics, errors) apply as |
| 135 | /// for the [`Handle::add_signal`] method. |
| 136 | pub fn new<I, S>(signals: I) -> Result<Self, Error> |
| 137 | where |
| 138 | I: IntoIterator<Item = S>, |
| 139 | S: Borrow<c_int>, |
| 140 | E: Default, |
| 141 | { |
| 142 | Self::with_exfiltrator(signals, E::default()) |
| 143 | } |
| 144 | |
| 145 | /// An advanced constructor with explicit [`Exfiltrator`]. |
| 146 | pub fn with_exfiltrator<I, S>(signals: I, exfiltrator: E) -> Result<Self, Error> |
| 147 | where |
| 148 | I: IntoIterator<Item = S>, |
| 149 | S: Borrow<c_int>, |
| 150 | { |
| 151 | let (read, write) = UnixStream::pair()?; |
| 152 | Ok(SignalsInfo(SignalDelivery::with_pipe( |
| 153 | read, |
| 154 | write, |
| 155 | exfiltrator, |
| 156 | signals, |
| 157 | )?)) |
| 158 | } |
| 159 | |
| 160 | /// Registers another signal to the set watched by this [`Signals`] instance. |
| 161 | /// |
| 162 | /// The same restrictions (panics, errors) apply as for the [`Handle::add_signal`] |
| 163 | /// method. |
| 164 | pub fn add_signal(&self, signal: c_int) -> Result<(), Error> { |
| 165 | self.handle().add_signal(signal) |
| 166 | } |
| 167 | |
| 168 | /// Returns an iterator of already received signals. |
| 169 | /// |
| 170 | /// This returns an iterator over all the signal numbers of the signals received since last |
| 171 | /// time they were read (out of the set registered by this `Signals` instance). Note that they |
| 172 | /// are returned in arbitrary order and a signal instance may returned only once even if it was |
| 173 | /// received multiple times. |
| 174 | /// |
| 175 | /// This method returns immediately (does not block) and may produce an empty iterator if there |
| 176 | /// are no signals ready. |
| 177 | pub fn pending(&mut self) -> Pending<E> { |
| 178 | self.0.pending() |
| 179 | } |
| 180 | |
| 181 | /// Block until the stream contains some bytes. |
| 182 | /// |
| 183 | /// Returns true if it was possible to read a byte and false otherwise. |
| 184 | fn has_signals(read: &mut UnixStream) -> Result<bool, Error> { |
| 185 | loop { |
| 186 | match read.read(&mut [0u8]) { |
| 187 | Ok(num_read) => break Ok(num_read > 0), |
| 188 | // If we get an EINTR error it is fine to retry reading from the stream. |
| 189 | // Otherwise we should pass on the error to the caller. |
| 190 | Err(error) => { |
| 191 | if error.kind() != ErrorKind::Interrupted { |
| 192 | break Err(error); |
| 193 | } |
| 194 | } |
| 195 | } |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | /// Waits for some signals to be available and returns an iterator. |
| 200 | /// |
| 201 | /// This is similar to [`pending`][SignalsInfo::pending]. If there are no signals available, it |
| 202 | /// tries to wait for some to arrive. However, due to implementation details, this still can |
| 203 | /// produce an empty iterator. |
| 204 | /// |
| 205 | /// This can block for arbitrary long time. If the [`Handle::close`] method is used in |
| 206 | /// another thread this method will return immediately. |
| 207 | /// |
| 208 | /// Note that the blocking is done in this method, not in the iterator. |
| 209 | pub fn wait(&mut self) -> Pending<E> { |
| 210 | match self.0.poll_pending(&mut Self::has_signals) { |
| 211 | Ok(Some(pending)) => pending, |
| 212 | // Because of the blocking has_signals method the poll_pending method |
| 213 | // only returns None if the instance is closed. But we want to return |
| 214 | // a possibly empty pending object anyway. |
| 215 | Ok(None) => self.pending(), |
| 216 | // Users can't manipulate the internal file descriptors and the way we use them |
| 217 | // shouldn't produce any errors. So it is OK to panic. |
| 218 | Err(error) => panic!("Unexpected error: {}" , error), |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | /// Is it closed? |
| 223 | /// |
| 224 | /// See [`close`][Handle::close]. |
| 225 | pub fn is_closed(&self) -> bool { |
| 226 | self.handle().is_closed() |
| 227 | } |
| 228 | |
| 229 | /// Get an infinite iterator over arriving signals. |
| 230 | /// |
| 231 | /// The iterator's `next()` blocks as necessary to wait for signals to arrive. This is adequate |
| 232 | /// if you want to designate a thread solely to handling signals. If multiple signals come at |
| 233 | /// the same time (between two values produced by the iterator), they will be returned in |
| 234 | /// arbitrary order. Multiple instances of the same signal may be collated. |
| 235 | /// |
| 236 | /// This is also the iterator returned by `IntoIterator` implementation on `&mut Signals`. |
| 237 | /// |
| 238 | /// This iterator terminates only if explicitly [closed][Handle::close]. |
| 239 | /// |
| 240 | /// # Examples |
| 241 | /// |
| 242 | /// ```rust |
| 243 | /// # extern crate libc; |
| 244 | /// # extern crate signal_hook; |
| 245 | /// # |
| 246 | /// # use std::io::Error; |
| 247 | /// # use std::thread; |
| 248 | /// # |
| 249 | /// use signal_hook::consts::signal::*; |
| 250 | /// use signal_hook::iterator::Signals; |
| 251 | /// |
| 252 | /// # fn main() -> Result<(), Error> { |
| 253 | /// let mut signals = Signals::new(&[SIGUSR1, SIGUSR2])?; |
| 254 | /// let handle = signals.handle(); |
| 255 | /// thread::spawn(move || { |
| 256 | /// for signal in signals.forever() { |
| 257 | /// match signal { |
| 258 | /// SIGUSR1 => {}, |
| 259 | /// SIGUSR2 => {}, |
| 260 | /// _ => unreachable!(), |
| 261 | /// } |
| 262 | /// } |
| 263 | /// }); |
| 264 | /// handle.close(); |
| 265 | /// # Ok(()) |
| 266 | /// # } |
| 267 | /// ``` |
| 268 | pub fn forever(&mut self) -> Forever<E> { |
| 269 | Forever(RefSignalIterator::new(&mut self.0)) |
| 270 | } |
| 271 | |
| 272 | /// Get a shareable handle to a [`Handle`] for this instance. |
| 273 | /// |
| 274 | /// This can be used to add further signals or close the [`Signals`] instance. |
| 275 | pub fn handle(&self) -> Handle { |
| 276 | self.0.handle() |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | impl<E> Debug for SignalsInfo<E> |
| 281 | where |
| 282 | E: Debug + Exfiltrator, |
| 283 | E::Storage: Debug, |
| 284 | { |
| 285 | fn fmt(&self, fmt: &mut Formatter) -> FmtResult { |
| 286 | fmt.debug_tuple(name:"Signals" ).field(&self.0).finish() |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | impl<'a, E: Exfiltrator> IntoIterator for &'a mut SignalsInfo<E> { |
| 291 | type Item = E::Output; |
| 292 | type IntoIter = Forever<'a, E>; |
| 293 | fn into_iter(self) -> Self::IntoIter { |
| 294 | self.forever() |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | /// An infinite iterator of arriving signals. |
| 299 | pub struct Forever<'a, E: Exfiltrator>(RefSignalIterator<'a, UnixStream, E>); |
| 300 | |
| 301 | impl<'a, E: Exfiltrator> Iterator for Forever<'a, E> { |
| 302 | type Item = E::Output; |
| 303 | |
| 304 | fn next(&mut self) -> Option<E::Output> { |
| 305 | loop { |
| 306 | match self.0.poll_signal(&mut SignalsInfo::<E>::has_signals) { |
| 307 | PollResult::Signal(result: ::Output) => break Some(result), |
| 308 | PollResult::Closed => break None, |
| 309 | // In theory, the poll_signal should not return PollResult::Pending. Nevertheless, |
| 310 | // there's a race condition - if the other side closes the pipe/socket after |
| 311 | // checking for it being closed, then the `read` there returns 0 as EOF. That |
| 312 | // appears as pending here. Next time we should get Closed. |
| 313 | PollResult::Pending => continue, |
| 314 | // Users can't manipulate the internal file descriptors and the way we use them |
| 315 | // shouldn't produce any errors. So it is OK to panic. |
| 316 | PollResult::Err(error: Error) => panic!("Unexpected error: {}" , error), |
| 317 | } |
| 318 | } |
| 319 | } |
| 320 | } |
| 321 | |
| 322 | /// A type alias for an iterator returning just the signal numbers. |
| 323 | /// |
| 324 | /// This is the simplified version for most of the use cases. For advanced usages, the |
| 325 | /// [`SignalsInfo`] with explicit [`Exfiltrator`] type can be used. |
| 326 | pub type Signals = SignalsInfo<SignalOnly>; |
| 327 | |