Выключение 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();
}