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}