Как ловить сигналы в 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.
}
Другие вопросы по тегам