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}