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
60pub mod backend;
61pub mod exfiltrator;
62
63use std::borrow::Borrow;
64use std::fmt::{Debug, Formatter, Result as FmtResult};
65use std::io::{Error, ErrorKind, Read};
66use std::os::unix::net::UnixStream;
67
68use libc::{self, c_int};
69
70pub use self::backend::{Handle, Pending};
71use self::backend::{PollResult, RefSignalIterator, SignalDelivery};
72use 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/// ```
129pub struct SignalsInfo<E: Exfiltrator = SignalOnly>(SignalDelivery<UnixStream, E>);
130
131impl<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
280impl<E> Debug for SignalsInfo<E>
281where
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
290impl<'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.
299pub struct Forever<'a, E: Exfiltrator>(RefSignalIterator<'a, UnixStream, E>);
300
301impl<'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.
326pub type Signals = SignalsInfo<SignalOnly>;
327