1 //! Unix-specific types for signal handling.
2 //!
3 //! This module is only defined on Unix platforms and contains the primary
4 //! `Signal` type for receiving notifications of signals.
5 
6 #![cfg(unix)]
7 
8 use crate::io::{AsyncRead, PollEvented};
9 use crate::signal::registry::{globals, EventId, EventInfo, Globals, Init, Storage};
10 use crate::sync::mpsc::{channel, Receiver};
11 
12 use libc::c_int;
13 use mio_uds::UnixStream;
14 use std::io::{self, Error, ErrorKind, Write};
15 use std::pin::Pin;
16 use std::sync::atomic::{AtomicBool, Ordering};
17 use std::sync::Once;
18 use std::task::{Context, Poll};
19 
20 pub(crate) type OsStorage = Vec<SignalInfo>;
21 
22 // Number of different unix signals
23 // (FreeBSD has 33)
24 const SIGNUM: usize = 33;
25 
26 impl Init for OsStorage {
27     fn init() -> Self {
28         (0..SIGNUM).map(|_| SignalInfo::default()).collect()
29     }
30 }
31 
32 impl Storage for OsStorage {
33     fn event_info(&self, id: EventId) -> Option<&EventInfo> {
34         self.get(id).map(|si| &si.event_info)
35     }
36 
37     fn for_each<'a, F>(&'a self, f: F)
38     where
39         F: FnMut(&'a EventInfo),
40     {
41         self.iter().map(|si| &si.event_info).for_each(f)
42     }
43 }
44 
45 #[derive(Debug)]
46 pub(crate) struct OsExtraData {
47     sender: UnixStream,
48     receiver: UnixStream,
49 }
50 
51 impl Init for OsExtraData {
52     fn init() -> Self {
53         let (receiver, sender) = UnixStream::pair().expect("failed to create UnixStream");
54 
55         Self { sender, receiver }
56     }
57 }
58 
59 /// Represents the specific kind of signal to listen for.
60 #[derive(Debug, Clone, Copy)]
61 pub struct SignalKind(c_int);
62 
63 impl SignalKind {
64     /// Allows for listening to any valid OS signal.
65     ///
66     /// For example, this can be used for listening for platform-specific
67     /// signals.
68     /// ```rust,no_run
69     /// # use tokio::signal::unix::SignalKind;
70     /// # let signum = -1;
71     /// // let signum = libc::OS_SPECIFIC_SIGNAL;
72     /// let kind = SignalKind::from_raw(signum);
73     /// ```
74     pub fn from_raw(signum: c_int) -> Self {
75         Self(signum)
76     }
77 
78     /// Represents the SIGALRM signal.
79     ///
80     /// On Unix systems this signal is sent when a real-time timer has expired.
81     /// By default, the process is terminated by this signal.
82     pub fn alarm() -> Self {
83         Self(libc::SIGALRM)
84     }
85 
86     /// Represents the SIGCHLD signal.
87     ///
88     /// On Unix systems this signal is sent when the status of a child process
89     /// has changed. By default, this signal is ignored.
90     pub fn child() -> Self {
91         Self(libc::SIGCHLD)
92     }
93 
94     /// Represents the SIGHUP signal.
95     ///
96     /// On Unix systems this signal is sent when the terminal is disconnected.
97     /// By default, the process is terminated by this signal.
98     pub fn hangup() -> Self {
99         Self(libc::SIGHUP)
100     }
101 
102     /// Represents the SIGINFO signal.
103     ///
104     /// On Unix systems this signal is sent to request a status update from the
105     /// process. By default, this signal is ignored.
106     #[cfg(any(
107         target_os = "dragonfly",
108         target_os = "freebsd",
109         target_os = "macos",
110         target_os = "netbsd",
111         target_os = "openbsd"
112     ))]
113     pub fn info() -> Self {
114         Self(libc::SIGINFO)
115     }
116 
117     /// Represents the SIGINT signal.
118     ///
119     /// On Unix systems this signal is sent to interrupt a program.
120     /// By default, the process is terminated by this signal.
121     pub fn interrupt() -> Self {
122         Self(libc::SIGINT)
123     }
124 
125     /// Represents the SIGIO signal.
126     ///
127     /// On Unix systems this signal is sent when I/O operations are possible
128     /// on some file descriptor. By default, this signal is ignored.
129     pub fn io() -> Self {
130         Self(libc::SIGIO)
131     }
132 
133     /// Represents the SIGPIPE signal.
134     ///
135     /// On Unix systems this signal is sent when the process attempts to write
136     /// to a pipe which has no reader. By default, the process is terminated by
137     /// this signal.
138     pub fn pipe() -> Self {
139         Self(libc::SIGPIPE)
140     }
141 
142     /// Represents the SIGQUIT signal.
143     ///
144     /// On Unix systems this signal is sent to issue a shutdown of the
145     /// process, after which the OS will dump the process core.
146     /// By default, the process is terminated by this signal.
147     pub fn quit() -> Self {
148         Self(libc::SIGQUIT)
149     }
150 
151     /// Represents the SIGTERM signal.
152     ///
153     /// On Unix systems this signal is sent to issue a shutdown of the
154     /// process. By default, the process is terminated by this signal.
155     pub fn terminate() -> Self {
156         Self(libc::SIGTERM)
157     }
158 
159     /// Represents the SIGUSR1 signal.
160     ///
161     /// On Unix systems this is a user defined signal.
162     /// By default, the process is terminated by this signal.
163     pub fn user_defined1() -> Self {
164         Self(libc::SIGUSR1)
165     }
166 
167     /// Represents the SIGUSR2 signal.
168     ///
169     /// On Unix systems this is a user defined signal.
170     /// By default, the process is terminated by this signal.
171     pub fn user_defined2() -> Self {
172         Self(libc::SIGUSR2)
173     }
174 
175     /// Represents the SIGWINCH signal.
176     ///
177     /// On Unix systems this signal is sent when the terminal window is resized.
178     /// By default, this signal is ignored.
179     pub fn window_change() -> Self {
180         Self(libc::SIGWINCH)
181     }
182 }
183 
184 pub(crate) struct SignalInfo {
185     event_info: EventInfo,
186     init: Once,
187     initialized: AtomicBool,
188 }
189 
190 impl Default for SignalInfo {
191     fn default() -> SignalInfo {
192         SignalInfo {
193             event_info: Default::default(),
194             init: Once::new(),
195             initialized: AtomicBool::new(false),
196         }
197     }
198 }
199 
200 /// Our global signal handler for all signals registered by this module.
201 ///
202 /// The purpose of this signal handler is to primarily:
203 ///
204 /// 1. Flag that our specific signal was received (e.g. store an atomic flag)
205 /// 2. Wake up driver tasks by writing a byte to a pipe
206 ///
207 /// Those two operations shoudl both be async-signal safe.
208 fn action(globals: Pin<&'static Globals>, signal: c_int) {
209     globals.record_event(signal as EventId);
210 
211     // Send a wakeup, ignore any errors (anything reasonably possible is
212     // full pipe and then it will wake up anyway).
213     let mut sender = &globals.sender;
214     drop(sender.write(&[1]));
215 }
216 
217 /// Enables this module to receive signal notifications for the `signal`
218 /// provided.
219 ///
220 /// This will register the signal handler if it hasn't already been registered,
221 /// returning any error along the way if that fails.
222 fn signal_enable(signal: c_int) -> io::Result<()> {
223     if signal < 0 || signal_hook_registry::FORBIDDEN.contains(&signal) {
224         return Err(Error::new(
225             ErrorKind::Other,
226             format!("Refusing to register signal {}", signal),
227         ));
228     }
229 
230     let globals = globals();
231     let siginfo = match globals.storage().get(signal as EventId) {
232         Some(slot) => slot,
233         None => return Err(io::Error::new(io::ErrorKind::Other, "signal too large")),
234     };
235     let mut registered = Ok(());
236     siginfo.init.call_once(|| {
237         registered = unsafe {
238             signal_hook_registry::register(signal, move || action(globals, signal)).map(|_| ())
239         };
240         if registered.is_ok() {
241             siginfo.initialized.store(true, Ordering::Relaxed);
242         }
243     });
244     registered?;
245     // If the call_once failed, it won't be retried on the next attempt to register the signal. In
246     // such case it is not run, registered is still `Ok(())`, initialized is still `false`.
247     if siginfo.initialized.load(Ordering::Relaxed) {
248         Ok(())
249     } else {
250         Err(Error::new(
251             ErrorKind::Other,
252             "Failed to register signal handler",
253         ))
254     }
255 }
256 
257 #[derive(Debug)]
258 struct Driver {
259     wakeup: PollEvented<UnixStream>,
260 }
261 
262 impl Driver {
263     fn poll(&mut self, cx: &mut Context<'_>) -> Poll<()> {
264         // Drain the data from the pipe and maintain interest in getting more
265         self.drain(cx);
266         // Broadcast any signals which were received
267         globals().broadcast();
268 
269         Poll::Pending
270     }
271 }
272 
273 impl Driver {
274     fn new() -> io::Result<Driver> {
275         // NB: We give each driver a "fresh" reciever file descriptor to avoid
276         // the issues described in alexcrichton/tokio-process#42.
277         //
278         // In the past we would reuse the actual receiver file descriptor and
279         // swallow any errors around double registration of the same descriptor.
280         // I'm not sure if the second (failed) registration simply doesn't end up
281         // receiving wake up notifications, or there could be some race condition
282         // when consuming readiness events, but having distinct descriptors for
283         // distinct PollEvented instances appears to mitigate this.
284         //
285         // Unfortunately we cannot just use a single global PollEvented instance
286         // either, since we can't compare Handles or assume they will always
287         // point to the exact same reactor.
288         let stream = globals().receiver.try_clone()?;
289         let wakeup = PollEvented::new(stream)?;
290 
291         Ok(Driver { wakeup })
292     }
293 
294     /// Drain all data in the global receiver, ensuring we'll get woken up when
295     /// there is a write on the other end.
296     ///
297     /// We do *NOT* use the existence of any read bytes as evidence a signal was
298     /// received since the `pending` flags would have already been set if that
299     /// was the case. See
300     /// [#38](https://github.com/alexcrichton/tokio-signal/issues/38) for more
301     /// info.
302     fn drain(&mut self, cx: &mut Context<'_>) {
303         loop {
304             match Pin::new(&mut self.wakeup).poll_read(cx, &mut [0; 128]) {
305                 Poll::Ready(Ok(0)) => panic!("EOF on self-pipe"),
306                 Poll::Ready(Ok(_)) => {}
307                 Poll::Ready(Err(e)) => panic!("Bad read on self-pipe: {}", e),
308                 Poll::Pending => break,
309             }
310         }
311     }
312 }
313 
314 /// A stream of events for receiving a particular type of OS signal.
315 ///
316 /// In general signal handling on Unix is a pretty tricky topic, and this
317 /// structure is no exception! There are some important limitations to keep in
318 /// mind when using `Signal` streams:
319 ///
320 /// * Signals handling in Unix already necessitates coalescing signals
321 ///   together sometimes. This `Signal` stream is also no exception here in
322 ///   that it will also coalesce signals. That is, even if the signal handler
323 ///   for this process runs multiple times, the `Signal` stream may only return
324 ///   one signal notification. Specifically, before `poll` is called, all
325 ///   signal notifications are coalesced into one item returned from `poll`.
326 ///   Once `poll` has been called, however, a further signal is guaranteed to
327 ///   be yielded as an item.
328 ///
329 ///   Put another way, any element pulled off the returned stream corresponds to
330 ///   *at least one* signal, but possibly more.
331 ///
332 /// * Signal handling in general is relatively inefficient. Although some
333 ///   improvements are possible in this crate, it's recommended to not plan on
334 ///   having millions of signal channels open.
335 ///
336 /// If you've got any questions about this feel free to open an issue on the
337 /// repo! New approaches to alleviate some of these limitations are always
338 /// appreciated!
339 ///
340 /// # Caveats
341 ///
342 /// The first time that a `Signal` instance is registered for a particular
343 /// signal kind, an OS signal-handler is installed which replaces the default
344 /// platform behavior when that signal is received, **for the duration of the
345 /// entire process**.
346 ///
347 /// For example, Unix systems will terminate a process by default when it
348 /// receives SIGINT. But, when a `Signal` instance is created to listen for
349 /// this signal, the next SIGINT that arrives will be translated to a stream
350 /// event, and the process will continue to execute. **Even if this `Signal`
351 /// instance is dropped, subsequent SIGINT deliveries will end up captured by
352 /// Tokio, and the default platform behavior will NOT be reset**.
353 ///
354 /// Thus, applications should take care to ensure the expected signal behavior
355 /// occurs as expected after listening for specific signals.
356 ///
357 /// # Examples
358 ///
359 /// Wait for SIGHUP
360 ///
361 /// ```rust,no_run
362 /// use tokio::signal::unix::{signal, SignalKind};
363 ///
364 /// #[tokio::main]
365 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
366 ///     // An infinite stream of hangup signals.
367 ///     let mut stream = signal(SignalKind::hangup())?;
368 ///
369 ///     // Print whenever a HUP signal is received
370 ///     loop {
371 ///         stream.recv().await;
372 ///         println!("got signal HUP");
373 ///     }
374 /// }
375 /// ```
376 #[must_use = "streams do nothing unless polled"]
377 #[derive(Debug)]
378 pub struct Signal {
379     driver: Driver,
380     rx: Receiver<()>,
381 }
382 
383 /// Creates a new stream which will receive notifications when the current
384 /// process receives the specified signal `kind`.
385 ///
386 /// This function will create a new stream which binds to the default reactor.
387 /// The `Signal` stream is an infinite stream which will receive
388 /// notifications whenever a signal is received. More documentation can be
389 /// found on `Signal` itself, but to reiterate:
390 ///
391 /// * Signals may be coalesced beyond what the kernel already does.
392 /// * Once a signal handler is registered with the process the underlying
393 ///   libc signal handler is never unregistered.
394 ///
395 /// A `Signal` stream can be created for a particular signal number
396 /// multiple times. When a signal is received then all the associated
397 /// channels will receive the signal notification.
398 ///
399 /// # Errors
400 ///
401 /// * If the lower-level C functions fail for some reason.
402 /// * If the previous initialization of this specific signal failed.
403 /// * If the signal is one of
404 ///   [`signal_hook::FORBIDDEN`](https://docs.rs/signal-hook/*/signal_hook/fn.register.html#panics)
405 pub fn signal(kind: SignalKind) -> io::Result<Signal> {
406     let signal = kind.0;
407 
408     // Turn the signal delivery on once we are ready for it
409     signal_enable(signal)?;
410 
411     // Ensure there's a driver for our associated event loop processing
412     // signals.
413     let driver = Driver::new()?;
414 
415     // One wakeup in a queue is enough, no need for us to buffer up any
416     // more.
417     let (tx, rx) = channel(1);
418     globals().register_listener(signal as EventId, tx);
419 
420     Ok(Signal { driver, rx })
421 }
422 
423 impl Signal {
424     /// Receives the next signal notification event.
425     ///
426     /// `None` is returned if no more events can be received by this stream.
427     ///
428     /// # Examples
429     ///
430     /// Wait for SIGHUP
431     ///
432     /// ```rust,no_run
433     /// use tokio::signal::unix::{signal, SignalKind};
434     ///
435     /// #[tokio::main]
436     /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
437     ///     // An infinite stream of hangup signals.
438     ///     let mut stream = signal(SignalKind::hangup())?;
439     ///
440     ///     // Print whenever a HUP signal is received
441     ///     loop {
442     ///         stream.recv().await;
443     ///         println!("got signal HUP");
444     ///     }
445     /// }
446     /// ```
447     pub async fn recv(&mut self) -> Option<()> {
448         use crate::future::poll_fn;
449         poll_fn(|cx| self.poll_recv(cx)).await
450     }
451 
452     /// Polls to receive the next signal notification event, outside of an
453     /// `async` context.
454     ///
455     /// `None` is returned if no more events can be received by this stream.
456     ///
457     /// # Examples
458     ///
459     /// Polling from a manually implemented future
460     ///
461     /// ```rust,no_run
462     /// use std::pin::Pin;
463     /// use std::future::Future;
464     /// use std::task::{Context, Poll};
465     /// use tokio::signal::unix::Signal;
466     ///
467     /// struct MyFuture {
468     ///     signal: Signal,
469     /// }
470     ///
471     /// impl Future for MyFuture {
472     ///     type Output = Option<()>;
473     ///
474     ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
475     ///         println!("polling MyFuture");
476     ///         self.signal.poll_recv(cx)
477     ///     }
478     /// }
479     /// ```
480     pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
481         let _ = self.driver.poll(cx);
482         self.rx.poll_recv(cx)
483     }
484 }
485 
486 cfg_stream! {
487     impl crate::stream::Stream for Signal {
488         type Item = ();
489 
490         fn poll_next(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<()>> {
491             self.poll_recv(cx)
492         }
493     }
494 }
495 
496 pub(crate) fn ctrl_c() -> io::Result<Signal> {
497     signal(SignalKind::interrupt())
498 }
499 
500 #[cfg(all(test, not(loom)))]
501 mod tests {
502     use super::*;
503 
504     #[test]
505     fn signal_enable_error_on_invalid_input() {
506         signal_enable(-1).unwrap_err();
507     }
508 
509     #[test]
510     fn signal_enable_error_on_forbidden_input() {
511         signal_enable(signal_hook_registry::FORBIDDEN[0]).unwrap_err();
512     }
513 }
514