Выключение actix с более чем одной работающей системой

Мое приложение основано на библиотеке (Library-A), которая использует actix и actix-web. Я добавляю вторую библиотеку (Library-B), которая работает на http-сервере, также используя actix-web. Я использую отдельную тему и actix::system за это. На SIGINT закрываются только системы actix Library-B, и библиотека-A работает. Никакой последующий SIGINT не закрывает работающую систему actix.

Как правильно изящно закрыть две работающие системы actix?

Код для Library-B, чтобы запустить новую систему actix и запустить http-сервер:

thread::spawn(move || {
    let sys = actix::System::new("monitor");
    server::new(|| App::new()
        .route("/metrics", http::Method::GET, endpoint))
        .bind(format!("0.0.0.0:{}", port))
        .unwrap()
        .start();
    sys.run();
    println!("Closing monitor actix system");
    // --- SIGINT gets me here... how do I shut down gracefully?
});

Правильно ли для меня запустить новую систему для независимой библиотеки? Как мне закрыть изящно?

1 ответ

Вы можете поймать Ctrl+C сигнал с использованием ctrlc crate.

Использование в основной теме можно найти в Rust-Lang-Nursery

Поскольку вы создаете свои потоки из своего основного потока и после того, как вы перехватили сигнал в своем основном потоке, вы можете корректно завершить работу других потоков, наблюдая за общим логическим значением в этих потоках.

В дополнение к этому есть функция остановки, специфичная для Actix.

Вы также можете использовать чан-сигнал ящик и написать свою собственную реализацию, как ответили здесь

Чтобы создать свою собственную логику выключения

Проверьте общее атомное логическое значение Arc во всех потоках и остановите выполнение при изменении этой переменной в основном потоке. Так как вы ловите ctrl-c Сигнал в основном потоке может уведомить другие потоки актера, например:

use ctrlc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;

fn main() {
    let running = Arc::new(AtomicBool::new(true));
    let running2 = running.clone();
    let r = running.clone();

    let thandle = thread::spawn(move || {
        while running2.load(Ordering::Relaxed) {
            //Do your logic here
        }
        println!("Thread1 stopped.")
    });

    let thandle2 = thread::spawn(move || {
        while running.load(Ordering::Relaxed) {
            //Do your different logic here
        }
        println!("Thread2 stopped.")
    });

    ctrlc::set_handler(move || {
        r.store(false, Ordering::Relaxed);
    })
    .expect("Error setting Ctrl-C handler");

    println!("Waiting for Ctrl-C...");
    let _ = thandle.join();
    let _ = thandle2.join();
}
Другие вопросы по тегам