Работать с сигналами сложно, и было бы слишком сложно объяснить, как обрабатывать все возможные случаи.Реализация сигналов не является стандартной для разных платформ, поэтому мой ответ специфичен для Linux.Если вы хотите быть более кроссплатформенным, используйте функцию POSIX sigaction
в сочетании с pause
;это даст вам больше контроля.
Один из способов добиться того, что вы хотите, - использовать ящик tokio_signal для перехвата сигналов, например: (пример документа)
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, так как мгновенно завершает работу программы.