我的应用程序基于使用actix和actix-web的库(Library-A)。我要添加第二个库(Library-B),它也使用actix-web运行http服务器。我为此使用了单独的线程和actix::system
。在SIGINT上,只有Library-B actix系统关闭,而Library-A仍在运行。随后没有SIGINT会关闭正在运行的actix系统。
正常关闭两个正在运行的actix系统的正确方法是什么?
库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?
});
为我的独立图书馆启动新系统对吗?如何正常关闭?
答案 0 :(得分:1)
使用ctrlc条板箱可以捕获Ctrl+C
信号。
主线程的用法可以在Rust-Lang-Nursery
中找到由于您是从主线程创建线程的,并且在捕获主线程中的信号之后,因此您可以通过观察这些线程中的共享布尔值来正常关闭其他线程。
此外,还有stop功能专门针对Actix。
您还可以使用chan-signal crate并编写您的自定义实现,例如已回答的here
创建自己的关机逻辑
在所有线程中检查共享的Arc原子布尔值,并在主线程中更改此变量后停止执行。由于您在主线程上捕获了ctrl-c
信号,因此它可以通知其他actor线程,如下所示:
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();
}