Как поймать сигналы в Rust
Я пытаюсь написать код, который поймает сигнал типа SIGTERM.
Я нашел this, и я также нашел Как обрабатывать блокировку ввода/вывода в Rust, или длительные вызовы внешних функций в целом.
Но в текущей версии Rust (0.12 в ночное время) кажется, что std::io::signal::Listener
был удален. Он попал куда-то еще? Если это так, кто-то может указать мне, как поймать сигнал?
Ответы
Ответ 1
Я считаю, что модуль std::io::signal
был удален в this pull request. Утверждается, что правильная обработка сигналов никогда не была должным образом реализована для собственной среды выполнения, поэтому вы, вероятно, не сможете ее использовать в любом случае. Это, кажется, проблема отслеживания этой проблемы.
Тем временем, я думаю, вам нужно будет спуститься до небезопасных функций самого низкого уровня из libc
.
Ответ 2
На момент написания этого ответа имеется 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.
}
Ответ 3
Кажется, что теперь это довольно тривиально реализовать это. Раздел Обработка сигналов в Приложениях командной строки в Rust выходит за рамки этой концепции и упоминает ящик 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(())
}