Как ловить сигналы в Rust
Я пытаюсь написать код, который будет ловить сигнал, такой как SIGTERM.
Я нашел это, и я также нашел, Как обрабатывать блокировку ввода- вывода в Rust или длительные вызовы внешних функций в целом.
Но в текущей версии Rust (0.12 по ночам) это выглядит так std::io::signal::Listener
был удален. Это было положено куда-то еще? Если так, может кто-нибудь указать мне, как поймать сигнал?
2 ответа
Я полагаю, что std::io::signal
модуль был удален в этом запросе. Утверждается, что надлежащая обработка сигналов никогда не была реализована должным образом для собственной среды выполнения, поэтому вы, вероятно, не сможете использовать ее сейчас в любом случае. Кажется, это проблема отслеживания этой проблемы.
В то же время, я думаю, вам придется перейти к небезопасным функциям самого низкого уровня из libc
,
Кажется, что реализовать это сейчас довольно просто. Обработки сигнала раздел командной строки приложений в Русте идет по концепции, и упоминает о CTRLC клети для обработки этого конкретного сигнала, и сигнал-крючок клеть для рукояток сигналов в целом.
С помощью направляющей и сигнального крючка все должно быть так просто:
use std::{error::Error, thread};
use signal_hook::{iterator::Signals, SIGTERM};
fn main() -> Result<(), Box<Error>> {
let signals = Signals::new(&[SIGTERM])?;
thread::spawn(move || {
for sig in signals.forever() {
println!("Received signal {:?}", sig);
}
});
Ok(())
}
На момент написания этого ответа имеется RFC для встроенных сигналов.
Я имел некоторый успех, используя chan-signal
ящик:
#[macro_use]
extern crate chan;
extern crate chan_signal;
use chan_signal::Signal;
fn main() {
// Signal gets a value when the OS sent a INT or TERM signal.
let signal = chan_signal::notify(&[Signal::INT, Signal::TERM]);
// When our work is complete, send a sentinel value on `sdone`.
let (sdone, rdone) = chan::sync(0);
// Run work.
::std::thread::spawn(move || run(sdone));
// Wait for a signal or for work to be done.
chan_select! {
signal.recv() -> signal => {
println!("received signal: {:?}", signal)
},
rdone.recv() => {
println!("Program completed normally.");
}
}
}
fn run(_sdone: chan::Sender<()>) {
println!("Running work for 5 seconds.");
println!("Can you send a signal quickly enough?");
// Do some work.
::std::thread::sleep_ms(5000);
// _sdone gets dropped which closes the channel and causes `rdone`
// to unblock.
}