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 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 
make_future(mut rx: Receiver<()>) -> Receiver<()>72 async fn make_future(mut rx: Receiver<()>) -> Receiver<()> {
73     match rx.changed().await {
74         Ok(()) => rx,
75         Err(_) => panic!("signal sender went away"),
76     }
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 crate::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