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. new<I, S>(signals: I) -> Result<Self, Error> where I: IntoIterator<Item = S>, S: Borrow<c_int>, E: Default,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`]. with_exfiltrator<I, S>(signals: I, exfiltrator: E) -> Result<Self, Error> where I: IntoIterator<Item = S>, S: Borrow<c_int>,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. add_signal(&self, signal: c_int) -> Result<(), Error>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. pending(&mut self) -> Pending<E>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. has_signals(read: &mut UnixStream) -> Result<bool, Error>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. wait(&mut self) -> Pending<E>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]. is_closed(&self) -> bool225 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 /// ``` forever(&mut self) -> Forever<E>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. handle(&self) -> Handle275 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 { fmt(&self, fmt: &mut Formatter) -> FmtResult285 fn fmt(&self, fmt: &mut Formatter) -> FmtResult { 286 fmt.debug_tuple("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>; into_iter(self) -> Self::IntoIter293 fn into_iter(self) -> Self::IntoIter { 294 self.forever() 295 } 296 } 297 298 /// An infinit 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 next(&mut self) -> Option<E::Output>304 fn next(&mut self) -> Option<E::Output> { 305 match self.0.poll_signal(&mut SignalsInfo::<E>::has_signals) { 306 PollResult::Signal(result) => Some(result), 307 PollResult::Closed => None, 308 PollResult::Pending => unreachable!( 309 "Because of the blocking has_signals method the \ 310 poll_signal method never returns Poll::Pending but blocks until a signal arrived" 311 ), 312 // Users can't manipulate the internal file descriptors and the way we use them 313 // shouldn't produce any errors. So it is OK to panic. 314 PollResult::Err(error) => panic!("Unexpected error: {}", error), 315 } 316 } 317 } 318 319 /// A type alias for an iterator returning just the signal numbers. 320 /// 321 /// This is the simplified version for most of the use cases. For advanced usages, the 322 /// [`SignalsInfo`] with explicit [`Exfiltrator`] type can be used. 323 pub type Signals = SignalsInfo<SignalOnly>; 324