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