1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
use std::{cell::RefCell, future::Future, pin::Pin, rc::Rc, task::Context, task::Poll};

use async_oneshot as oneshot;

thread_local! {
    static SRUN: RefCell<bool> = RefCell::new(false);
    static SHANDLERS: Rc<RefCell<Vec<oneshot::Sender<Signal>>>> = Default::default();
}

/// Different types of process signals
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum Signal {
    /// SIGHUP
    Hup,
    /// SIGINT
    Int,
    /// SIGTERM
    Term,
    /// SIGQUIT
    Quit,
}

/// Register signal handler.
///
/// Signals are handled by oneshots, you have to re-register
/// after each signal.
pub fn signal() -> Option<oneshot::Receiver<Signal>> {
    if !SRUN.with(|v| *v.borrow()) {
        async_std::task::spawn_local(Signals::new());
    }
    SHANDLERS.with(|handlers| {
        let (tx, rx) = oneshot::oneshot();
        handlers.borrow_mut().push(tx);
        Some(rx)
    })
}

struct Signals {}

impl Signals {
    pub(super) fn new() -> Signals {
        Self {}
    }
}

impl Future for Signals {
    type Output = ();

    fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
        Poll::Ready(())
    }
}