9

我有一个main函数,我在其中创建一个 Tokio 运行时并在其上运行两个期货。

use tokio;

fn main() {
    let mut runtime = tokio::runtime::Runtime::new().unwrap();

    runtime.spawn(MyMegaFutureNumberOne {});
    runtime.spawn(MyMegaFutureNumberTwo {});

    // Some code to 'join' them after receiving an OS signal
}

我如何收到一个SIGTERM,等待所有未完成NotReady的任务并退出应用程序?

4

2 回答 2

11

处理信号很棘手,解释如何处理所有可能的情况太宽泛了。信号的实现不是跨平台的标准,所以我的回答是针对 Linux 的。如果你想更跨平台,sigaction结合使用 POSIX 函数pause;这将为您提供更多控制权。

实现您想要的一种方法是使用tokio_signal crate 来捕获信号,如下所示:(doc example)

extern crate futures;
extern crate tokio;
extern crate tokio_signal;

use futures::prelude::*;
use futures::Stream;
use std::time::{Duration, Instant};
use tokio_signal::unix::{Signal, SIGINT, SIGTERM};

fn main() -> Result<(), Box<::std::error::Error>> {
    let mut runtime = tokio::runtime::Runtime::new()?;

    let sigint = Signal::new(SIGINT).flatten_stream();
    let sigterm = Signal::new(SIGTERM).flatten_stream();

    let stream = sigint.select(sigterm);

    let deadline = tokio::timer::Delay::new(Instant::now() + Duration::from_secs(5))
        .map(|()| println!("5 seconds are over"))
        .map_err(|e| eprintln!("Failed to wait: {}", e));

    runtime.spawn(deadline);

    let (item, _rest) = runtime
        .block_on_all(stream.into_future())
        .map_err(|_| "failed to wait for signals")?;

    let item = item.ok_or("received no signal")?;
    if item == SIGINT {
        println!("received SIGINT");
    } else {
        assert_eq!(item, SIGTERM);
        println!("received SIGTERM");
    }

    Ok(())
}

该程序将等待所有当前任务完成并捕获选定的信号。这似乎不适用于 Windows,因为它会立即关闭程序。

于 2018-11-27T18:14:52.427 回答
2

另一个答案是 Tokio 版本 0.1.x,它非常旧。对于 Tokio 版本 1.xy,Tokio 官方教程有一个关于此主题的页面:Graceful shutdown

于 2021-09-01T07:06:40.480 回答