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
use futures::future::{FusedFuture, FutureExt};

pub async fn with_signal_handler<F, E>(mut f: F) -> Result<(), E>
where
    F: FusedFuture<Output = Result<(), E>> + Unpin,
{
    futures::select! {
        result = f => result,
        _ = watch_signal().fuse() => Ok(()),
    }
}

#[cfg(unix)]
async fn watch_signal() {
    use tokio::signal::unix::{signal, SignalKind};

    let mut hsigterm =
        signal(SignalKind::interrupt()).expect("failed to install handler for SIGTERM");
    let mut hsigint =
        signal(SignalKind::terminate()).expect("failed to install handler for SIGTINT");

    let hsigterm_future = hsigterm.recv();
    let hsigint_future = hsigint.recv();

    tokio::pin!(hsigterm_future);
    tokio::pin!(hsigint_future);

    futures::future::select(hsigterm_future, hsigint_future).await;
    eprintln!("stopped upon receiving SIGTERM or SIGINT");
}

#[cfg(not(unix))]
async fn watch_signal() {
    use tokio::signal::ctrl_c;

    ctrl_c().await.expect("failed to wait for Ctrl-C");
    eprintln!("stopped by an external signal");
}