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