1 //! Windows-specific types for signal handling.
2 //!
3 //! This module is only defined on Windows and allows receiving "ctrl-c"
4 //! and "ctrl-break" notifications. These events are listened for via the
5 //! `SetConsoleCtrlHandler` function which receives events of the type
6 //! `CTRL_C_EVENT` and `CTRL_BREAK_EVENT`.
7 
8 #![cfg(any(windows, docsrs))]
9 #![cfg_attr(docsrs, doc(cfg(all(windows, feature = "signal"))))]
10 
11 use crate::signal::RxFuture;
12 use std::io;
13 use std::task::{Context, Poll};
14 
15 #[cfg(not(docsrs))]
16 #[path = "windows/sys.rs"]
17 mod imp;
18 #[cfg(not(docsrs))]
19 pub(crate) use self::imp::{OsExtraData, OsStorage};
20 
21 #[cfg(docsrs)]
22 #[path = "windows/stub.rs"]
23 mod imp;
24 
25 /// Creates a new stream which receives "ctrl-c" notifications sent to the
26 /// process.
27 ///
28 /// # Examples
29 ///
30 /// ```rust,no_run
31 /// use tokio::signal::windows::ctrl_c;
32 ///
33 /// #[tokio::main]
34 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
35 ///     // An infinite stream of CTRL-C events.
36 ///     let mut stream = ctrl_c()?;
37 ///
38 ///     // Print whenever a CTRL-C event is received.
39 ///     for countdown in (0..3).rev() {
40 ///         stream.recv().await;
41 ///         println!("got CTRL-C. {} more to exit", countdown);
42 ///     }
43 ///
44 ///     Ok(())
45 /// }
46 /// ```
ctrl_c() -> io::Result<CtrlC>47 pub fn ctrl_c() -> io::Result<CtrlC> {
48     Ok(CtrlC {
49         inner: self::imp::ctrl_c()?,
50     })
51 }
52 
53 /// Represents a stream which receives "ctrl-c" notifications sent to the process
54 /// via `SetConsoleCtrlHandler`.
55 ///
56 /// A notification to this process notifies *all* streams listening for
57 /// this event. Moreover, the notifications **are coalesced** if they aren't processed
58 /// quickly enough. This means that if two notifications are received back-to-back,
59 /// then the stream may only receive one item about the two notifications.
60 #[must_use = "streams do nothing unless polled"]
61 #[derive(Debug)]
62 pub struct CtrlC {
63     inner: RxFuture,
64 }
65 
66 impl CtrlC {
67     /// Receives the next signal notification event.
68     ///
69     /// `None` is returned if no more events can be received by this stream.
70     ///
71     /// # Examples
72     ///
73     /// ```rust,no_run
74     /// use tokio::signal::windows::ctrl_c;
75     ///
76     /// #[tokio::main]
77     /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
78     ///     // An infinite stream of CTRL-C events.
79     ///     let mut stream = ctrl_c()?;
80     ///
81     ///     // Print whenever a CTRL-C event is received.
82     ///     for countdown in (0..3).rev() {
83     ///         stream.recv().await;
84     ///         println!("got CTRL-C. {} more to exit", countdown);
85     ///     }
86     ///
87     ///     Ok(())
88     /// }
89     /// ```
recv(&mut self) -> Option<()>90     pub async fn recv(&mut self) -> Option<()> {
91         self.inner.recv().await
92     }
93 
94     /// Polls to receive the next signal notification event, outside of an
95     /// `async` context.
96     ///
97     /// `None` is returned if no more events can be received by this stream.
98     ///
99     /// # Examples
100     ///
101     /// Polling from a manually implemented future
102     ///
103     /// ```rust,no_run
104     /// use std::pin::Pin;
105     /// use std::future::Future;
106     /// use std::task::{Context, Poll};
107     /// use tokio::signal::windows::CtrlC;
108     ///
109     /// struct MyFuture {
110     ///     ctrl_c: CtrlC,
111     /// }
112     ///
113     /// impl Future for MyFuture {
114     ///     type Output = Option<()>;
115     ///
116     ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
117     ///         println!("polling MyFuture");
118     ///         self.ctrl_c.poll_recv(cx)
119     ///     }
120     /// }
121     /// ```
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>122     pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
123         self.inner.poll_recv(cx)
124     }
125 }
126 
127 /// Represents a stream which receives "ctrl-break" notifications sent to the process
128 /// via `SetConsoleCtrlHandler`.
129 ///
130 /// A notification to this process notifies *all* streams listening for
131 /// this event. Moreover, the notifications **are coalesced** if they aren't processed
132 /// quickly enough. This means that if two notifications are received back-to-back,
133 /// then the stream may only receive one item about the two notifications.
134 #[must_use = "streams do nothing unless polled"]
135 #[derive(Debug)]
136 pub struct CtrlBreak {
137     inner: RxFuture,
138 }
139 
140 impl CtrlBreak {
141     /// Receives the next signal notification event.
142     ///
143     /// `None` is returned if no more events can be received by this stream.
144     ///
145     /// # Examples
146     ///
147     /// ```rust,no_run
148     /// use tokio::signal::windows::ctrl_break;
149     ///
150     /// #[tokio::main]
151     /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
152     ///     // An infinite stream of CTRL-BREAK events.
153     ///     let mut stream = ctrl_break()?;
154     ///
155     ///     // Print whenever a CTRL-BREAK event is received.
156     ///     loop {
157     ///         stream.recv().await;
158     ///         println!("got signal CTRL-BREAK");
159     ///     }
160     /// }
161     /// ```
recv(&mut self) -> Option<()>162     pub async fn recv(&mut self) -> Option<()> {
163         self.inner.recv().await
164     }
165 
166     /// Polls to receive the next signal notification event, outside of an
167     /// `async` context.
168     ///
169     /// `None` is returned if no more events can be received by this stream.
170     ///
171     /// # Examples
172     ///
173     /// Polling from a manually implemented future
174     ///
175     /// ```rust,no_run
176     /// use std::pin::Pin;
177     /// use std::future::Future;
178     /// use std::task::{Context, Poll};
179     /// use tokio::signal::windows::CtrlBreak;
180     ///
181     /// struct MyFuture {
182     ///     ctrl_break: CtrlBreak,
183     /// }
184     ///
185     /// impl Future for MyFuture {
186     ///     type Output = Option<()>;
187     ///
188     ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
189     ///         println!("polling MyFuture");
190     ///         self.ctrl_break.poll_recv(cx)
191     ///     }
192     /// }
193     /// ```
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>194     pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
195         self.inner.poll_recv(cx)
196     }
197 }
198 
199 /// Creates a new stream which receives "ctrl-break" notifications sent to the
200 /// process.
201 ///
202 /// # Examples
203 ///
204 /// ```rust,no_run
205 /// use tokio::signal::windows::ctrl_break;
206 ///
207 /// #[tokio::main]
208 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
209 ///     // An infinite stream of CTRL-BREAK events.
210 ///     let mut stream = ctrl_break()?;
211 ///
212 ///     // Print whenever a CTRL-BREAK event is received.
213 ///     loop {
214 ///         stream.recv().await;
215 ///         println!("got signal CTRL-BREAK");
216 ///     }
217 /// }
218 /// ```
ctrl_break() -> io::Result<CtrlBreak>219 pub fn ctrl_break() -> io::Result<CtrlBreak> {
220     Ok(CtrlBreak {
221         inner: self::imp::ctrl_break()?,
222     })
223 }
224