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}