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 
make_future(mut rx: Receiver<()>) -> Receiver<()>74 async fn make_future(mut rx: Receiver<()>) -> Receiver<()> {
75     rx.changed().await.expect("signal sender went away");
76     rx
77 }
78 
79 impl RxFuture {
new(rx: Receiver<()>) -> Self80     fn new(rx: Receiver<()>) -> Self {
81         Self {
82             inner: ReusableBoxFuture::new(make_future(rx)),
83         }
84     }
85 
recv(&mut self) -> Option<()>86     async fn recv(&mut self) -> Option<()> {
87         use std::future::poll_fn;
88         poll_fn(|cx| self.poll_recv(cx)).await
89     }
90 
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>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) => {
95                 self.inner.set(make_future(rx));
96                 Poll::Ready(Some(()))
97             }
98         }
99     }
100 }
101