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