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