1 //! Windows-specific types for signal handling.
2 //!
3 //! This module is only defined on Windows and allows receiving "ctrl-c",
4 //! "ctrl-break", "ctrl-logoff", "ctrl-shutdown", and "ctrl-close"
5 //! notifications. These events are listened for via the `SetConsoleCtrlHandler`
6 //! function which receives the corresponding windows_sys event type.
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
225 /// Creates a new stream which receives "ctrl-close" notifications sent to the
226 /// process.
227 ///
228 /// # Examples
229 ///
230 /// ```rust,no_run
231 /// use tokio::signal::windows::ctrl_close;
232 ///
233 /// #[tokio::main]
234 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
235 /// // An infinite stream of CTRL-CLOSE events.
236 /// let mut stream = ctrl_close()?;
237 ///
238 /// // Print whenever a CTRL-CLOSE event is received.
239 /// for countdown in (0..3).rev() {
240 /// stream.recv().await;
241 /// println!("got CTRL-CLOSE. {} more to exit", countdown);
242 /// }
243 ///
244 /// Ok(())
245 /// }
246 /// ```
ctrl_close() -> io::Result<CtrlClose>247 pub fn ctrl_close() -> io::Result<CtrlClose> {
248 Ok(CtrlClose {
249 inner: self::imp::ctrl_close()?,
250 })
251 }
252
253 /// Represents a stream which receives "ctrl-close" notitifications sent to the process
254 /// via 'SetConsoleCtrlHandler'.
255 ///
256 /// A notification to this process notifies *all* streams listening for
257 /// this event. Moreover, the notifications **are coalesced** if they aren't processed
258 /// quickly enough. This means that if two notifications are received back-to-back,
259 /// then the stream may only receive one item about the two notifications.
260 #[must_use = "streams do nothing unless polled"]
261 #[derive(Debug)]
262 pub struct CtrlClose {
263 inner: RxFuture,
264 }
265
266 impl CtrlClose {
267 /// Receives the next signal notification event.
268 ///
269 /// `None` is returned if no more events can be received by this stream.
270 ///
271 /// # Examples
272 ///
273 /// ```rust,no_run
274 /// use tokio::signal::windows::ctrl_close;
275 ///
276 /// #[tokio::main]
277 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
278 /// // An infinite stream of CTRL-CLOSE events.
279 /// let mut stream = ctrl_close()?;
280 ///
281 /// // Print whenever a CTRL-CLOSE event is received.
282 /// stream.recv().await;
283 /// println!("got CTRL-CLOSE. Cleaning up before exiting");
284 ///
285 /// Ok(())
286 /// }
287 /// ```
recv(&mut self) -> Option<()>288 pub async fn recv(&mut self) -> Option<()> {
289 self.inner.recv().await
290 }
291
292 /// Polls to receive the next signal notification event, outside of an
293 /// `async` context.
294 ///
295 /// `None` is returned if no more events can be received by this stream.
296 ///
297 /// # Examples
298 ///
299 /// Polling from a manually implemented future
300 ///
301 /// ```rust,no_run
302 /// use std::pin::Pin;
303 /// use std::future::Future;
304 /// use std::task::{Context, Poll};
305 /// use tokio::signal::windows::CtrlClose;
306 ///
307 /// struct MyFuture {
308 /// ctrl_close: CtrlClose,
309 /// }
310 ///
311 /// impl Future for MyFuture {
312 /// type Output = Option<()>;
313 ///
314 /// fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
315 /// println!("polling MyFuture");
316 /// self.ctrl_close.poll_recv(cx)
317 /// }
318 /// }
319 /// ```
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>320 pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
321 self.inner.poll_recv(cx)
322 }
323 }
324
325 /// Creates a new stream which receives "ctrl-shutdown" notifications sent to the
326 /// process.
327 ///
328 /// # Examples
329 ///
330 /// ```rust,no_run
331 /// use tokio::signal::windows::ctrl_shutdown;
332 ///
333 /// #[tokio::main]
334 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
335 /// // An infinite stream of CTRL-SHUTDOWN events.
336 /// let mut stream = ctrl_shutdown()?;
337 ///
338 /// stream.recv().await;
339 /// println!("got CTRL-SHUTDOWN. Cleaning up before exiting");
340 ///
341 /// Ok(())
342 /// }
343 /// ```
ctrl_shutdown() -> io::Result<CtrlShutdown>344 pub fn ctrl_shutdown() -> io::Result<CtrlShutdown> {
345 Ok(CtrlShutdown {
346 inner: self::imp::ctrl_shutdown()?,
347 })
348 }
349
350 /// Represents a stream which receives "ctrl-shutdown" notitifications sent to the process
351 /// via 'SetConsoleCtrlHandler'.
352 ///
353 /// A notification to this process notifies *all* streams listening for
354 /// this event. Moreover, the notifications **are coalesced** if they aren't processed
355 /// quickly enough. This means that if two notifications are received back-to-back,
356 /// then the stream may only receive one item about the two notifications.
357 #[must_use = "streams do nothing unless polled"]
358 #[derive(Debug)]
359 pub struct CtrlShutdown {
360 inner: RxFuture,
361 }
362
363 impl CtrlShutdown {
364 /// Receives the next signal notification event.
365 ///
366 /// `None` is returned if no more events can be received by this stream.
367 ///
368 /// # Examples
369 ///
370 /// ```rust,no_run
371 /// use tokio::signal::windows::ctrl_shutdown;
372 ///
373 /// #[tokio::main]
374 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
375 /// // An infinite stream of CTRL-SHUTDOWN events.
376 /// let mut stream = ctrl_shutdown()?;
377 ///
378 /// // Print whenever a CTRL-SHUTDOWN event is received.
379 /// stream.recv().await;
380 /// println!("got CTRL-SHUTDOWN. Cleaning up before exiting");
381 ///
382 /// Ok(())
383 /// }
384 /// ```
recv(&mut self) -> Option<()>385 pub async fn recv(&mut self) -> Option<()> {
386 self.inner.recv().await
387 }
388
389 /// Polls to receive the next signal notification event, outside of an
390 /// `async` context.
391 ///
392 /// `None` is returned if no more events can be received by this stream.
393 ///
394 /// # Examples
395 ///
396 /// Polling from a manually implemented future
397 ///
398 /// ```rust,no_run
399 /// use std::pin::Pin;
400 /// use std::future::Future;
401 /// use std::task::{Context, Poll};
402 /// use tokio::signal::windows::CtrlShutdown;
403 ///
404 /// struct MyFuture {
405 /// ctrl_shutdown: CtrlShutdown,
406 /// }
407 ///
408 /// impl Future for MyFuture {
409 /// type Output = Option<()>;
410 ///
411 /// fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
412 /// println!("polling MyFuture");
413 /// self.ctrl_shutdown.poll_recv(cx)
414 /// }
415 /// }
416 /// ```
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>417 pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
418 self.inner.poll_recv(cx)
419 }
420 }
421
422 /// Creates a new stream which receives "ctrl-logoff" notifications sent to the
423 /// process.
424 ///
425 /// # Examples
426 ///
427 /// ```rust,no_run
428 /// use tokio::signal::windows::ctrl_logoff;
429 ///
430 /// #[tokio::main]
431 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
432 /// // An infinite stream of CTRL-LOGOFF events.
433 /// let mut stream = ctrl_logoff()?;
434 ///
435 /// stream.recv().await;
436 /// println!("got CTRL-LOGOFF. Cleaning up before exiting");
437 ///
438 /// Ok(())
439 /// }
440 /// ```
ctrl_logoff() -> io::Result<CtrlLogoff>441 pub fn ctrl_logoff() -> io::Result<CtrlLogoff> {
442 Ok(CtrlLogoff {
443 inner: self::imp::ctrl_logoff()?,
444 })
445 }
446
447 /// Represents a stream which receives "ctrl-logoff" notitifications sent to the process
448 /// via 'SetConsoleCtrlHandler'.
449 ///
450 /// A notification to this process notifies *all* streams listening for
451 /// this event. Moreover, the notifications **are coalesced** if they aren't processed
452 /// quickly enough. This means that if two notifications are received back-to-back,
453 /// then the stream may only receive one item about the two notifications.
454 #[must_use = "streams do nothing unless polled"]
455 #[derive(Debug)]
456 pub struct CtrlLogoff {
457 inner: RxFuture,
458 }
459
460 impl CtrlLogoff {
461 /// Receives the next signal notification event.
462 ///
463 /// `None` is returned if no more events can be received by this stream.
464 ///
465 /// # Examples
466 ///
467 /// ```rust,no_run
468 /// use tokio::signal::windows::ctrl_logoff;
469 ///
470 /// #[tokio::main]
471 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
472 /// // An infinite stream of CTRL-LOGOFF events.
473 /// let mut stream = ctrl_logoff()?;
474 ///
475 /// // Print whenever a CTRL-LOGOFF event is received.
476 /// stream.recv().await;
477 /// println!("got CTRL-LOGOFF. Cleaning up before exiting");
478 ///
479 /// Ok(())
480 /// }
481 /// ```
recv(&mut self) -> Option<()>482 pub async fn recv(&mut self) -> Option<()> {
483 self.inner.recv().await
484 }
485
486 /// Polls to receive the next signal notification event, outside of an
487 /// `async` context.
488 ///
489 /// `None` is returned if no more events can be received by this stream.
490 ///
491 /// # Examples
492 ///
493 /// Polling from a manually implemented future
494 ///
495 /// ```rust,no_run
496 /// use std::pin::Pin;
497 /// use std::future::Future;
498 /// use std::task::{Context, Poll};
499 /// use tokio::signal::windows::CtrlLogoff;
500 ///
501 /// struct MyFuture {
502 /// ctrl_logoff: CtrlLogoff,
503 /// }
504 ///
505 /// impl Future for MyFuture {
506 /// type Output = Option<()>;
507 ///
508 /// fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
509 /// println!("polling MyFuture");
510 /// self.ctrl_logoff.poll_recv(cx)
511 /// }
512 /// }
513 /// ```
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>514 pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
515 self.inner.poll_recv(cx)
516 }
517 }
518