• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 use crate::signal::RxFuture;
12 use std::io;
13 use std::task::{Context, Poll};
14 
15 #[cfg(not(docsrs))]
16 #[path = "windows/sys.rs"]
17 mod imp;
18 #[cfg(not(docsrs))]
19 pub(crate) use self::imp::{OsExtraData, OsStorage};
20 
21 #[cfg(docsrs)]
22 #[path = "windows/stub.rs"]
23 mod 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 /// ```
ctrl_c() -> io::Result<CtrlC>47 pub 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)]
66 pub struct CtrlC {
67     inner: RxFuture,
68 }
69 
70 impl 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     /// ```
recv(&mut self) -> Option<()>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     /// ```
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>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)]
143 pub struct CtrlBreak {
144     inner: RxFuture,
145 }
146 
147 impl 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     /// ```
recv(&mut self) -> Option<()>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     /// ```
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>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 /// ```
ctrl_break() -> io::Result<CtrlBreak>226 pub 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 /// ```
ctrl_close() -> io::Result<CtrlClose>254 pub 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" notitifications 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)]
269 pub struct CtrlClose {
270     inner: RxFuture,
271 }
272 
273 impl 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     /// ```
recv(&mut self) -> Option<()>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     /// ```
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>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 /// ```
ctrl_shutdown() -> io::Result<CtrlShutdown>351 pub 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" notitifications 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)]
366 pub struct CtrlShutdown {
367     inner: RxFuture,
368 }
369 
370 impl 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     /// ```
recv(&mut self) -> Option<()>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     /// ```
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>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 /// ```
ctrl_logoff() -> io::Result<CtrlLogoff>448 pub 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" notitifications 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)]
463 pub struct CtrlLogoff {
464     inner: RxFuture,
465 }
466 
467 impl 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     /// ```
recv(&mut self) -> Option<()>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     /// ```
poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>521     pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
522         self.inner.poll_recv(cx)
523     }
524 }
525