1 //! Windows-specific types for signal handling.
2 //!
3 //! This module is only defined on Windows and allows receiving "ctrl-c"
4 //! and "ctrl-break" notifications. These events are listened for via the
5 //! `SetConsoleCtrlHandler` function which receives events of the type
6 //! `CTRL_C_EVENT` and `CTRL_BREAK_EVENT`.
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