代码之家  ›  专栏  ›  技术社区  ›  hedgar2017

如何优雅地关闭Tokio运行时以响应SIGTERM?

  •  3
  • hedgar2017  · 技术社区  · 6 年前

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

    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 s) 然后退出应用程序?

    1 回复  |  直到 6 年前
        1
  •  10
  •   Shepmaster Tim Diekmann    6 年前

    处理信号是一件棘手的事情,要解释如何处理所有可能的案件,这一点太宽泛了。信号的实现不是跨平台的标准,因此我的答案是针对Linux的。如果您想更跨平台,请使用POSIX函数 sigaction 与…结合 pause ; 这将为您提供更多的控制。

    tokio_signal (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(())
    }