1 | //! Asynchronous signal handling for Tokio. |
2 | //! |
3 | //! Note that signal handling is in general a very tricky topic and should be |
4 | //! used with great care. This crate attempts to implement 'best practice' for |
5 | //! signal handling, but it should be evaluated for your own applications' needs |
6 | //! to see if it's suitable. |
7 | //! |
8 | //! There are some fundamental limitations of this crate documented on the OS |
9 | //! specific structures, as well. |
10 | //! |
11 | //! # Examples |
12 | //! |
13 | //! Print on "ctrl-c" notification. |
14 | //! |
15 | //! ```rust,no_run |
16 | //! use tokio::signal; |
17 | //! |
18 | //! #[tokio::main] |
19 | //! async fn main() -> Result<(), Box<dyn std::error::Error>> { |
20 | //! signal::ctrl_c().await?; |
21 | //! println!("ctrl-c received!" ); |
22 | //! Ok(()) |
23 | //! } |
24 | //! ``` |
25 | //! |
26 | //! Wait for SIGHUP on Unix |
27 | //! |
28 | //! ```rust,no_run |
29 | //! # #[cfg (unix)] { |
30 | //! use tokio::signal::unix::{signal, SignalKind}; |
31 | //! |
32 | //! #[tokio::main] |
33 | //! async fn main() -> Result<(), Box<dyn std::error::Error>> { |
34 | //! // An infinite stream of hangup signals. |
35 | //! let mut stream = signal(SignalKind::hangup())?; |
36 | //! |
37 | //! // Print whenever a HUP signal is received |
38 | //! loop { |
39 | //! stream.recv().await; |
40 | //! println!("got signal HUP" ); |
41 | //! } |
42 | //! } |
43 | //! # } |
44 | //! ``` |
45 | use crate::sync::watch::Receiver; |
46 | use std::task::{Context, Poll}; |
47 | |
48 | mod ctrl_c; |
49 | pub use ctrl_c::ctrl_c; |
50 | |
51 | pub(crate) mod registry; |
52 | |
53 | mod os { |
54 | #[cfg (unix)] |
55 | pub(crate) use super::unix::{OsExtraData, OsStorage}; |
56 | |
57 | #[cfg (windows)] |
58 | pub(crate) use super::windows::{OsExtraData, OsStorage}; |
59 | } |
60 | |
61 | pub mod unix; |
62 | pub mod windows; |
63 | |
64 | mod reusable_box; |
65 | use self::reusable_box::ReusableBoxFuture; |
66 | |
67 | #[derive(Debug)] |
68 | struct RxFuture { |
69 | inner: ReusableBoxFuture<Receiver<()>>, |
70 | } |
71 | |
72 | async fn make_future(mut rx: Receiver<()>) -> Receiver<()> { |
73 | rx.changed().await.expect("signal sender went away" ); |
74 | rx |
75 | } |
76 | |
77 | impl RxFuture { |
78 | fn new(rx: Receiver<()>) -> Self { |
79 | Self { |
80 | inner: ReusableBoxFuture::new(make_future(rx)), |
81 | } |
82 | } |
83 | |
84 | async fn recv(&mut self) -> Option<()> { |
85 | use crate::future::poll_fn; |
86 | poll_fn(|cx| self.poll_recv(cx)).await |
87 | } |
88 | |
89 | fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> { |
90 | match self.inner.poll(cx) { |
91 | Poll::Pending => Poll::Pending, |
92 | Poll::Ready(rx) => { |
93 | self.inner.set(make_future(rx)); |
94 | Poll::Ready(Some(())) |
95 | } |
96 | } |
97 | } |
98 | } |
99 | |