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