1#![doc(test(attr(deny(warnings))))]
2#![warn(missing_docs)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5//! A crate offering integration with the MIO runtime.
6//!
7//! There are different sub modules for supporting different MIO
8//! versions. The support for a version must be activated by a
9//! feature flag:
10//!
11//! * `support-v0_6` for sub module [`v0_6`]
12//! * `support-v0_7` for sub module [`v0_7`]
13//! * `support-v0_8` for sub module [`v0_8`]
14//!
15//! See the specific sub modules for usage examples.
16
17#[cfg(any(
18 feature = "support-v0_6",
19 feature = "support-v0_7",
20 feature = "support-v0_8"
21))]
22macro_rules! implement_signals_with_pipe {
23 ($pipe:path) => {
24 use std::borrow::Borrow;
25 use std::io::Error;
26
27 use signal_hook::iterator::backend::{self, SignalDelivery};
28 use signal_hook::iterator::exfiltrator::{Exfiltrator, SignalOnly};
29
30 use $pipe as Pipe;
31
32 use libc::c_int;
33
34 /// A struct which mimics [`signal_hook::iterator::SignalsInfo`]
35 /// but also allows usage together with MIO runtime.
36 pub struct SignalsInfo<E: Exfiltrator = SignalOnly>(SignalDelivery<Pipe, E>);
37
38 pub use backend::Pending;
39
40 impl<E: Exfiltrator> SignalsInfo<E> {
41 /// Create a `Signals` instance.
42 ///
43 /// This registers all the signals listed. The same restrictions (panics, errors) apply
44 /// as with [`Handle::add_signal`][backend::Handle::add_signal].
45 pub fn new<I, S>(signals: I) -> Result<Self, Error>
46 where
47 I: IntoIterator<Item = S>,
48 S: Borrow<c_int>,
49 E: Default,
50 {
51 Self::with_exfiltrator(signals, E::default())
52 }
53
54 /// A constructor with specifying an exfiltrator to pass information out of the signal
55 /// handlers.
56 pub fn with_exfiltrator<I, S>(signals: I, exfiltrator: E) -> Result<Self, Error>
57 where
58 I: IntoIterator<Item = S>,
59 S: Borrow<c_int>,
60 {
61 let (read, write) = Pipe::pair()?;
62 let delivery = SignalDelivery::with_pipe(read, write, exfiltrator, signals)?;
63 Ok(Self(delivery))
64 }
65
66 /// Registers another signal to the set watched by this [`Signals`] instance.
67 ///
68 /// The same restrictions (panics, errors) apply as with
69 /// [`Handle::add_signal`][backend::Handle::add_signal].
70 pub fn add_signal(&self, signal: c_int) -> Result<(), Error> {
71 self.0.handle().add_signal(signal)
72 }
73
74 /// Returns an iterator of already received signals.
75 ///
76 /// This returns an iterator over all the signal numbers of the signals received since last
77 /// time they were read (out of the set registered by this `Signals` instance). Note that they
78 /// are returned in arbitrary order and a signal number is returned only once even if it was
79 /// received multiple times.
80 ///
81 /// This method returns immediately (does not block) and may produce an empty iterator if there
82 /// are no signals ready. So you should register an instance of this struct at an instance of
83 /// [`mio::Poll`] to query for readability of the underlying self pipe.
84 pub fn pending(&mut self) -> Pending<E> {
85 self.0.pending()
86 }
87 }
88
89 /// A simplified signal iterator.
90 ///
91 /// This is the [`SignalsInfo`], but returning only the signal numbers. This is likely the
92 /// one you want to use.
93 pub type Signals = SignalsInfo<SignalOnly>;
94 };
95}
96
97/// A module for integrating signal handling with the MIO 0.8 runtime.
98///
99/// This provides the [`Signals`][v0_8::Signals] struct as an abstraction
100/// which can be used with [`mio::Poll`][mio_0_8::Poll].
101///
102/// # Examples
103///
104/// ```rust
105/// # use mio_0_8 as mio;
106/// use std::io::{Error, ErrorKind};
107///
108/// use signal_hook::consts::signal::*;
109/// use signal_hook_mio::v0_8::Signals;
110///
111/// use mio::{Events, Poll, Interest, Token};
112///
113/// fn main() -> Result<(), Error> {
114/// let mut poll = Poll::new()?;
115///
116/// let mut signals = Signals::new(&[
117/// SIGTERM,
118/// # SIGUSR1,
119/// ])?;
120///
121/// let signal_token = Token(0);
122///
123/// poll.registry().register(&mut signals, signal_token, Interest::READABLE)?;
124/// # signal_hook::low_level::raise(SIGUSR1).unwrap(); // Just for terminating the example
125///
126/// let mut events = Events::with_capacity(10);
127/// 'outer: loop {
128/// poll.poll(&mut events, None)
129/// .or_else(|e| if e.kind() == ErrorKind::Interrupted {
130/// // We get interrupt when a signal happens inside poll. That's non-fatal, just
131/// // retry.
132/// events.clear();
133/// Ok(())
134/// } else {
135/// Err(e)
136/// })?;
137/// for event in events.iter() {
138/// match event.token() {
139/// Token(0) => {
140/// for signal in signals.pending() {
141/// match signal {
142/// SIGTERM => break 'outer,
143/// # SIGUSR1 => return Ok(()),
144/// _ => unreachable!(),
145/// }
146/// }
147/// },
148/// _ => unreachable!("Register other sources and match for their tokens here"),
149/// }
150/// }
151/// }
152///
153/// Ok(())
154/// }
155/// ```
156#[cfg(feature = "support-v0_8")]
157pub mod v0_8 {
158 use mio::event::Source;
159 use mio::{Interest, Registry, Token};
160 use mio_0_8 as mio;
161
162 implement_signals_with_pipe!(mio::net::UnixStream);
163
164 impl Source for Signals {
165 fn register(
166 &mut self,
167 registry: &Registry,
168 token: Token,
169 interest: Interest,
170 ) -> Result<(), Error> {
171 self.0.get_read_mut().register(registry, token, interest)
172 }
173
174 fn reregister(
175 &mut self,
176 registry: &Registry,
177 token: Token,
178 interest: Interest,
179 ) -> Result<(), Error> {
180 self.0.get_read_mut().reregister(registry, token, interest)
181 }
182
183 fn deregister(&mut self, registry: &Registry) -> Result<(), Error> {
184 self.0.get_read_mut().deregister(registry)
185 }
186 }
187}
188
189/// A module for integrating signal handling with the MIO 0.7 runtime.
190///
191/// This provides the [`Signals`][v0_7::Signals] struct as an abstraction
192/// which can be used with [`mio::Poll`][mio_0_7::Poll].
193///
194/// # Examples
195///
196/// ```rust
197/// # use mio_0_7 as mio;
198/// use std::io::{Error, ErrorKind};
199///
200/// use signal_hook::consts::signal::*;
201/// use signal_hook_mio::v0_7::Signals;
202///
203/// use mio::{Events, Poll, Interest, Token};
204///
205/// fn main() -> Result<(), Error> {
206/// let mut poll = Poll::new()?;
207///
208/// let mut signals = Signals::new(&[
209/// SIGTERM,
210/// # SIGUSR1,
211/// ])?;
212///
213/// let signal_token = Token(0);
214///
215/// poll.registry().register(&mut signals, signal_token, Interest::READABLE)?;
216/// # signal_hook::low_level::raise(SIGUSR1).unwrap(); // Just for terminating the example
217///
218/// let mut events = Events::with_capacity(10);
219/// 'outer: loop {
220/// poll.poll(&mut events, None)
221/// .or_else(|e| if e.kind() == ErrorKind::Interrupted {
222/// // We get interrupt when a signal happens inside poll. That's non-fatal, just
223/// // retry.
224/// events.clear();
225/// Ok(())
226/// } else {
227/// Err(e)
228/// })?;
229/// for event in events.iter() {
230/// match event.token() {
231/// Token(0) => {
232/// for signal in signals.pending() {
233/// match signal {
234/// SIGTERM => break 'outer,
235/// # SIGUSR1 => return Ok(()),
236/// _ => unreachable!(),
237/// }
238/// }
239/// },
240/// _ => unreachable!("Register other sources and match for their tokens here"),
241/// }
242/// }
243/// }
244///
245/// Ok(())
246/// }
247/// ```
248#[cfg(feature = "support-v0_7")]
249pub mod v0_7 {
250 use mio::event::Source;
251 use mio::{Interest, Registry, Token};
252 use mio_0_7 as mio;
253
254 implement_signals_with_pipe!(mio::net::UnixStream);
255
256 impl Source for Signals {
257 fn register(
258 &mut self,
259 registry: &Registry,
260 token: Token,
261 interest: Interest,
262 ) -> Result<(), Error> {
263 self.0.get_read_mut().register(registry, token, interest)
264 }
265
266 fn reregister(
267 &mut self,
268 registry: &Registry,
269 token: Token,
270 interest: Interest,
271 ) -> Result<(), Error> {
272 self.0.get_read_mut().reregister(registry, token, interest)
273 }
274
275 fn deregister(&mut self, registry: &Registry) -> Result<(), Error> {
276 self.0.get_read_mut().deregister(registry)
277 }
278 }
279}
280
281/// A module for integrating signal handling with the MIO 0.6 runtime.
282///
283/// This provides the [`Signals`][v0_6::Signals] struct as an abstraction
284/// which can be used with [`mio::Poll`][mio_0_6::Poll].
285///
286/// # Examples
287///
288/// ```rust
289/// # use mio_0_6 as mio;
290/// use std::io::{Error, ErrorKind};
291///
292/// use signal_hook::consts::signal::*;
293/// use signal_hook_mio::v0_6::Signals;
294///
295/// use mio::{Events, Poll, PollOpt, Ready, Token};
296///
297/// fn main() -> Result<(), Error> {
298/// let poll = Poll::new()?;
299///
300/// let mut signals = Signals::new(&[
301/// SIGTERM,
302/// # SIGUSR1,
303/// ])?;
304///
305/// let signal_token = Token(0);
306///
307/// poll.register(&mut signals, signal_token, Ready::readable(), PollOpt::level())?;
308/// # signal_hook::low_level::raise(SIGUSR1).unwrap(); // Just for terminating the example
309///
310/// let mut events = Events::with_capacity(10);
311/// 'outer: loop {
312/// poll.poll(&mut events, None)
313/// .or_else(|e| if e.kind() == ErrorKind::Interrupted {
314/// // We get interrupt when a signal happens inside poll. That's non-fatal, just
315/// // retry.
316/// events.clear();
317/// Ok(0)
318/// } else {
319/// Err(e)
320/// })?;
321/// for event in events.iter() {
322/// match event.token() {
323/// Token(0) => {
324/// for signal in signals.pending() {
325/// match signal {
326/// SIGTERM => break 'outer,
327/// # SIGUSR1 => return Ok(()),
328/// _ => unreachable!(),
329/// }
330/// }
331/// },
332/// _ => unreachable!("Register other sources and match for their tokens here"),
333/// }
334/// }
335/// }
336///
337/// Ok(())
338/// }
339/// ```
340#[cfg(feature = "support-v0_6")]
341pub mod v0_6 {
342
343 use mio::event::Evented;
344 use mio::{Poll, PollOpt, Ready, Token};
345 use mio_0_6 as mio;
346
347 implement_signals_with_pipe!(mio_uds::UnixStream);
348
349 impl Evented for Signals {
350 fn register(
351 &self,
352 poll: &Poll,
353 token: Token,
354 interest: Ready,
355 opts: PollOpt,
356 ) -> Result<(), Error> {
357 self.0.get_read().register(poll, token, interest, opts)
358 }
359
360 fn reregister(
361 &self,
362 poll: &Poll,
363 token: Token,
364 interest: Ready,
365 opts: PollOpt,
366 ) -> Result<(), Error> {
367 self.0.get_read().reregister(poll, token, interest, opts)
368 }
369
370 fn deregister(&self, poll: &Poll) -> Result<(), Error> {
371 self.0.get_read().deregister(poll)
372 }
373 }
374}
375