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
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