Skip to main content

tokio/signal/
windows.rs

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
11use crate::signal::RxFuture;
12use std::io;
13use std::task::{Context, Poll};
14
15#[cfg(windows)]
16#[path = "windows/sys.rs"]
17mod imp;
18
19// For building documentation on Unix machines when the `docsrs` flag is set.
20#[cfg(not(windows))]
21#[path = "windows/stub.rs"]
22mod imp;
23
24/// Creates a new listener which receives "ctrl-c" notifications sent to the
25/// process.
26///
27/// # Examples
28///
29/// ```rust,no_run
30/// use tokio::signal::windows::ctrl_c;
31///
32/// #[tokio::main]
33/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
34///     // A listener of CTRL-C events.
35///     let mut signal = ctrl_c()?;
36///
37///     // Print whenever a CTRL-C event is received.
38///     for countdown in (0..3).rev() {
39///         signal.recv().await;
40///         println!("got CTRL-C. {} more to exit", countdown);
41///     }
42///
43///     Ok(())
44/// }
45/// ```
46pub fn ctrl_c() -> io::Result<CtrlC> {
47    Ok(CtrlC {
48        inner: self::imp::ctrl_c()?,
49    })
50}
51
52/// Represents a listener which receives "ctrl-c" notifications sent to the process
53/// via `SetConsoleCtrlHandler`.
54///
55/// This event can be turned into a `Stream` using [`CtrlCStream`].
56///
57/// [`CtrlCStream`]: https://docs.rs/tokio-stream/latest/tokio_stream/wrappers/struct.CtrlCStream.html
58///
59/// A notification to this process notifies *all* receivers for
60/// this event. Moreover, the notifications **are coalesced** if they aren't processed
61/// quickly enough. This means that if two notifications are received back-to-back,
62/// then the listener may only receive one item about the two notifications.
63#[must_use = "listeners do nothing unless polled"]
64#[derive(Debug)]
65pub struct CtrlC {
66    inner: RxFuture,
67}
68
69impl CtrlC {
70    /// Receives the next signal notification event.
71    ///
72    /// Although this returns `Option<()>`, it will never actually return `None`.
73    /// This was accidentally exposed and would be a breaking change to be removed.
74    ///
75    /// # Examples
76    ///
77    /// ```rust,no_run
78    /// use tokio::signal::windows::ctrl_c;
79    ///
80    /// #[tokio::main]
81    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
82    ///     let mut signal = ctrl_c()?;
83    ///
84    ///     // Print whenever a CTRL-C event is received.
85    ///     for countdown in (0..3).rev() {
86    ///         signal.recv().await;
87    ///         println!("got CTRL-C. {} more to exit", countdown);
88    ///     }
89    ///
90    ///     Ok(())
91    /// }
92    /// ```
93    pub async fn recv(&mut self) -> Option<()> {
94        self.inner.recv().await;
95        Some(())
96    }
97
98    /// Polls to receive the next signal notification event, outside of an
99    /// `async` context.
100    ///
101    /// Although this returns `Option<()>`, it will never actually return `None`.
102    /// This was accidentally exposed and would be a breaking change to be removed.
103    ///
104    /// # Examples
105    ///
106    /// Polling from a manually implemented future
107    ///
108    /// ```rust,no_run
109    /// use std::pin::Pin;
110    /// use std::future::Future;
111    /// use std::task::{Context, Poll};
112    /// use tokio::signal::windows::CtrlC;
113    ///
114    /// struct MyFuture {
115    ///     ctrl_c: CtrlC,
116    /// }
117    ///
118    /// impl Future for MyFuture {
119    ///     type Output = Option<()>;
120    ///
121    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
122    ///         println!("polling MyFuture");
123    ///         self.ctrl_c.poll_recv(cx)
124    ///     }
125    /// }
126    /// ```
127    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
128        self.inner.poll_recv(cx).map(Some)
129    }
130}
131
132/// Represents a listener which receives "ctrl-break" notifications sent to the process
133/// via `SetConsoleCtrlHandler`.
134///
135/// This listener can be turned into a `Stream` using [`CtrlBreakStream`].
136///
137/// [`CtrlBreakStream`]: https://docs.rs/tokio-stream/latest/tokio_stream/wrappers/struct.CtrlBreakStream.html
138///
139/// A notification to this process notifies *all* receivers for
140/// this event. Moreover, the notifications **are coalesced** if they aren't processed
141/// quickly enough. This means that if two notifications are received back-to-back,
142/// then the listener may only receive one item about the two notifications.
143#[must_use = "listeners do nothing unless polled"]
144#[derive(Debug)]
145pub struct CtrlBreak {
146    inner: RxFuture,
147}
148
149impl CtrlBreak {
150    /// Receives the next signal notification event.
151    ///
152    /// Although this returns `Option<()>`, it will never actually return `None`.
153    /// This was accidentally exposed and would be a breaking change to be removed.
154    ///
155    /// # Examples
156    ///
157    /// ```rust,no_run
158    /// use tokio::signal::windows::ctrl_break;
159    ///
160    /// #[tokio::main]
161    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
162    ///     // A listener of CTRL-BREAK events.
163    ///     let mut signal = ctrl_break()?;
164    ///
165    ///     // Print whenever a CTRL-BREAK event is received.
166    ///     loop {
167    ///         signal.recv().await;
168    ///         println!("got signal CTRL-BREAK");
169    ///     }
170    /// }
171    /// ```
172    pub async fn recv(&mut self) -> Option<()> {
173        self.inner.recv().await;
174        Some(())
175    }
176
177    /// Polls to receive the next signal notification event, outside of an
178    /// `async` context.
179    ///
180    /// Although this returns `Option<()>`, it will never actually return `None`.
181    /// This was accidentally exposed and would be a breaking change to be removed.
182    ///
183    /// # Examples
184    ///
185    /// Polling from a manually implemented future
186    ///
187    /// ```rust,no_run
188    /// use std::pin::Pin;
189    /// use std::future::Future;
190    /// use std::task::{Context, Poll};
191    /// use tokio::signal::windows::CtrlBreak;
192    ///
193    /// struct MyFuture {
194    ///     ctrl_break: CtrlBreak,
195    /// }
196    ///
197    /// impl Future for MyFuture {
198    ///     type Output = Option<()>;
199    ///
200    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
201    ///         println!("polling MyFuture");
202    ///         self.ctrl_break.poll_recv(cx)
203    ///     }
204    /// }
205    /// ```
206    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
207        self.inner.poll_recv(cx).map(Some)
208    }
209}
210
211/// Creates a new listener which receives "ctrl-break" notifications sent to the
212/// process.
213///
214/// # Examples
215///
216/// ```rust,no_run
217/// use tokio::signal::windows::ctrl_break;
218///
219/// #[tokio::main]
220/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
221///     // A listener of CTRL-BREAK events.
222///     let mut signal = ctrl_break()?;
223///
224///     // Print whenever a CTRL-BREAK event is received.
225///     loop {
226///         signal.recv().await;
227///         println!("got signal CTRL-BREAK");
228///     }
229/// }
230/// ```
231pub fn ctrl_break() -> io::Result<CtrlBreak> {
232    Ok(CtrlBreak {
233        inner: self::imp::ctrl_break()?,
234    })
235}
236
237/// Creates a new listener which receives "ctrl-close" notifications sent to the
238/// process.
239///
240/// # Examples
241///
242/// ```rust,no_run
243/// use tokio::signal::windows::ctrl_close;
244///
245/// #[tokio::main]
246/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
247///     // A listener of CTRL-CLOSE events.
248///     let mut signal = ctrl_close()?;
249///
250///     // Print whenever a CTRL-CLOSE event is received.
251///     for countdown in (0..3).rev() {
252///         signal.recv().await;
253///         println!("got CTRL-CLOSE. {} more to exit", countdown);
254///     }
255///
256///     Ok(())
257/// }
258/// ```
259pub fn ctrl_close() -> io::Result<CtrlClose> {
260    Ok(CtrlClose {
261        inner: self::imp::ctrl_close()?,
262    })
263}
264
265/// Represents a listener which receives "ctrl-close" notifications sent to the process
266/// via `SetConsoleCtrlHandler`.
267///
268/// A notification to this process notifies *all* listeners listening for
269/// this event. Moreover, the notifications **are coalesced** if they aren't processed
270/// quickly enough. This means that if two notifications are received back-to-back,
271/// then the listener may only receive one item about the two notifications.
272#[must_use = "listeners do nothing unless polled"]
273#[derive(Debug)]
274pub struct CtrlClose {
275    inner: RxFuture,
276}
277
278impl CtrlClose {
279    /// Receives the next signal notification event.
280    ///
281    /// Although this returns `Option<()>`, it will never actually return `None`.
282    /// This was accidentally exposed and would be a breaking change to be removed.
283    ///
284    /// # Examples
285    ///
286    /// ```rust,no_run
287    /// use tokio::signal::windows::ctrl_close;
288    ///
289    /// #[tokio::main]
290    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
291    ///     // A listener of CTRL-CLOSE events.
292    ///     let mut signal = ctrl_close()?;
293    ///
294    ///     // Print whenever a CTRL-CLOSE event is received.
295    ///     signal.recv().await;
296    ///     println!("got CTRL-CLOSE. Cleaning up before exiting");
297    ///
298    ///     Ok(())
299    /// }
300    /// ```
301    pub async fn recv(&mut self) -> Option<()> {
302        self.inner.recv().await;
303        Some(())
304    }
305
306    /// Polls to receive the next signal notification event, outside of an
307    /// `async` context.
308    ///
309    /// Although this returns `Option<()>`, it will never actually return `None`.
310    /// This was accidentally exposed and would be a breaking change to be removed.
311    ///
312    /// # Examples
313    ///
314    /// Polling from a manually implemented future
315    ///
316    /// ```rust,no_run
317    /// use std::pin::Pin;
318    /// use std::future::Future;
319    /// use std::task::{Context, Poll};
320    /// use tokio::signal::windows::CtrlClose;
321    ///
322    /// struct MyFuture {
323    ///     ctrl_close: CtrlClose,
324    /// }
325    ///
326    /// impl Future for MyFuture {
327    ///     type Output = Option<()>;
328    ///
329    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
330    ///         println!("polling MyFuture");
331    ///         self.ctrl_close.poll_recv(cx)
332    ///     }
333    /// }
334    /// ```
335    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
336        self.inner.poll_recv(cx).map(Some)
337    }
338}
339
340/// Creates a new listener which receives "ctrl-shutdown" notifications sent to the
341/// process.
342///
343/// # Examples
344///
345/// ```rust,no_run
346/// use tokio::signal::windows::ctrl_shutdown;
347///
348/// #[tokio::main]
349/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
350///     // A listener of CTRL-SHUTDOWN events.
351///     let mut signal = ctrl_shutdown()?;
352///
353///     signal.recv().await;
354///     println!("got CTRL-SHUTDOWN. Cleaning up before exiting");
355///
356///     Ok(())
357/// }
358/// ```
359pub fn ctrl_shutdown() -> io::Result<CtrlShutdown> {
360    Ok(CtrlShutdown {
361        inner: self::imp::ctrl_shutdown()?,
362    })
363}
364
365/// Represents a listener which receives "ctrl-shutdown" notifications sent to the process
366/// via `SetConsoleCtrlHandler`.
367///
368/// A notification to this process notifies *all* listeners listening for
369/// this event. Moreover, the notifications **are coalesced** if they aren't processed
370/// quickly enough. This means that if two notifications are received back-to-back,
371/// then the listener may only receive one item about the two notifications.
372#[must_use = "listeners do nothing unless polled"]
373#[derive(Debug)]
374pub struct CtrlShutdown {
375    inner: RxFuture,
376}
377
378impl CtrlShutdown {
379    /// Receives the next signal notification event.
380    ///
381    /// Although this returns `Option<()>`, it will never actually return `None`.
382    /// This was accidentally exposed and would be a breaking change to be removed.
383    ///
384    /// # Examples
385    ///
386    /// ```rust,no_run
387    /// use tokio::signal::windows::ctrl_shutdown;
388    ///
389    /// #[tokio::main]
390    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
391    ///     // A listener of CTRL-SHUTDOWN events.
392    ///     let mut signal = ctrl_shutdown()?;
393    ///
394    ///     // Print whenever a CTRL-SHUTDOWN event is received.
395    ///     signal.recv().await;
396    ///     println!("got CTRL-SHUTDOWN. Cleaning up before exiting");
397    ///
398    ///     Ok(())
399    /// }
400    /// ```
401    pub async fn recv(&mut self) -> Option<()> {
402        self.inner.recv().await;
403        Some(())
404    }
405
406    /// Polls to receive the next signal notification event, outside of an
407    /// `async` context.
408    ///
409    /// Although this returns `Option<()>`, it will never actually return `None`.
410    /// This was accidentally exposed and would be a breaking change to be removed.
411    ///
412    /// # Examples
413    ///
414    /// Polling from a manually implemented future
415    ///
416    /// ```rust,no_run
417    /// use std::pin::Pin;
418    /// use std::future::Future;
419    /// use std::task::{Context, Poll};
420    /// use tokio::signal::windows::CtrlShutdown;
421    ///
422    /// struct MyFuture {
423    ///     ctrl_shutdown: CtrlShutdown,
424    /// }
425    ///
426    /// impl Future for MyFuture {
427    ///     type Output = Option<()>;
428    ///
429    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
430    ///         println!("polling MyFuture");
431    ///         self.ctrl_shutdown.poll_recv(cx)
432    ///     }
433    /// }
434    /// ```
435    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
436        self.inner.poll_recv(cx).map(Some)
437    }
438}
439
440/// Creates a new listener which receives "ctrl-logoff" notifications sent to the
441/// process.
442///
443/// # Examples
444///
445/// ```rust,no_run
446/// use tokio::signal::windows::ctrl_logoff;
447///
448/// #[tokio::main]
449/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
450///     // A listener of CTRL-LOGOFF events.
451///     let mut signal = ctrl_logoff()?;
452///
453///     signal.recv().await;
454///     println!("got CTRL-LOGOFF. Cleaning up before exiting");
455///
456///     Ok(())
457/// }
458/// ```
459pub fn ctrl_logoff() -> io::Result<CtrlLogoff> {
460    Ok(CtrlLogoff {
461        inner: self::imp::ctrl_logoff()?,
462    })
463}
464
465/// Represents a listener which receives "ctrl-logoff" notifications sent to the process
466/// via `SetConsoleCtrlHandler`.
467///
468/// A notification to this process notifies *all* listeners listening for
469/// this event. Moreover, the notifications **are coalesced** if they aren't processed
470/// quickly enough. This means that if two notifications are received back-to-back,
471/// then the listener may only receive one item about the two notifications.
472#[must_use = "listeners do nothing unless polled"]
473#[derive(Debug)]
474pub struct CtrlLogoff {
475    inner: RxFuture,
476}
477
478impl CtrlLogoff {
479    /// Receives the next signal notification event.
480    ///
481    /// Although this returns `Option<()>`, it will never actually return `None`.
482    /// This was accidentally exposed and would be a breaking change to be removed.
483    ///
484    /// # Examples
485    ///
486    /// ```rust,no_run
487    /// use tokio::signal::windows::ctrl_logoff;
488    ///
489    /// #[tokio::main]
490    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
491    ///     // An listener of CTRL-LOGOFF events.
492    ///     let mut signal = ctrl_logoff()?;
493    ///
494    ///     // Print whenever a CTRL-LOGOFF event is received.
495    ///     signal.recv().await;
496    ///     println!("got CTRL-LOGOFF. Cleaning up before exiting");
497    ///
498    ///     Ok(())
499    /// }
500    /// ```
501    pub async fn recv(&mut self) -> Option<()> {
502        self.inner.recv().await;
503        Some(())
504    }
505
506    /// Polls to receive the next signal notification event, outside of an
507    /// `async` context.
508    ///
509    /// Although this returns `Option<()>`, it will never actually return `None`.
510    /// This was accidentally exposed and would be a breaking change to be removed.
511    ///
512    /// # Examples
513    ///
514    /// Polling from a manually implemented future
515    ///
516    /// ```rust,no_run
517    /// use std::pin::Pin;
518    /// use std::future::Future;
519    /// use std::task::{Context, Poll};
520    /// use tokio::signal::windows::CtrlLogoff;
521    ///
522    /// struct MyFuture {
523    ///     ctrl_logoff: CtrlLogoff,
524    /// }
525    ///
526    /// impl Future for MyFuture {
527    ///     type Output = Option<()>;
528    ///
529    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
530    ///         println!("polling MyFuture");
531    ///         self.ctrl_logoff.poll_recv(cx)
532    ///     }
533    /// }
534    /// ```
535    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
536        self.inner.poll_recv(cx).map(Some)
537    }
538}