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 | #[cfg (feature = "signal" )] |
49 | mod ctrl_c; |
50 | #[cfg (feature = "signal" )] |
51 | pub use ctrl_c::ctrl_c; |
52 | |
53 | pub(crate) mod registry; |
54 | |
55 | mod os { |
56 | #[cfg (unix)] |
57 | pub(crate) use super::unix::{OsExtraData, OsStorage}; |
58 | |
59 | #[cfg (windows)] |
60 | pub(crate) use super::windows::{OsExtraData, OsStorage}; |
61 | } |
62 | |
63 | pub mod unix; |
64 | pub mod windows; |
65 | |
66 | mod reusable_box; |
67 | use self::reusable_box::ReusableBoxFuture; |
68 | |
69 | #[derive (Debug)] |
70 | struct RxFuture { |
71 | inner: ReusableBoxFuture<Receiver<()>>, |
72 | } |
73 | |
74 | async fn make_future(mut rx: Receiver<()>) -> Receiver<()> { |
75 | rx.changed().await.expect(msg:"signal sender went away" ); |
76 | rx |
77 | } |
78 | |
79 | impl RxFuture { |
80 | fn new(rx: Receiver<()>) -> Self { |
81 | Self { |
82 | inner: ReusableBoxFuture::new(make_future(rx)), |
83 | } |
84 | } |
85 | |
86 | async fn recv(&mut self) -> Option<()> { |
87 | use std::future::poll_fn; |
88 | poll_fn(|cx: &mut Context<'_>| self.poll_recv(cx)).await |
89 | } |
90 | |
91 | fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> { |
92 | match self.inner.poll(cx) { |
93 | Poll::Pending => Poll::Pending, |
94 | Poll::Ready(rx: Receiver<()>) => { |
95 | self.inner.set(make_future(rx)); |
96 | Poll::Ready(Some(())) |
97 | } |
98 | } |
99 | } |
100 | } |
101 | |