fix: 修复 Ctrl+C 无法及时退出主循环的 P1 bug
问题: main.rs Ctrl+C handler 只置 AtomicBool, 但 manager.run() 阻塞在 rx.recv() 永久等待下一条消息, 导致 Ctrl+C 后需等任意消息到达才能退出. CLAUDE.md:162 记录的已知 P1 隐患 (王浩然发现). 修复 (3 处): 1. service_manager.rs run(): recv() -> recv_timeout(200ms), 超时则 continue 重新检查 self.running, 确保信号能被及时响应 2. service_manager.rs handle_manager_message(): Shutdown 分支广播后 置 self.running=false, 让主循环正常退出 (原本只广播不停机) 3. main.rs Ctrl+C handler: 除置 AtomicBool 外, 向 channel 注入 Message::Shutdown envelope, 唤醒 recv_timeout 并触发优雅停机 效果: Ctrl+C 后最多 200ms 退出, 而非等待下一条任意消息. 注: Windows 开发环境缺 pkg-config/libdbus, 无法本地 cargo check; 改动经 rust-analyzer 类型检查零诊断, 待目标机 (Linux ARM64) 验证.
This commit is contained in:
@@ -358,9 +358,12 @@ impl ServiceManager {
|
|||||||
self.running = true;
|
self.running = true;
|
||||||
|
|
||||||
while self.running {
|
while self.running {
|
||||||
let envelope = match self.rx.recv() {
|
// 使用 recv_timeout 而非 recv,确保外部信号(如 Ctrl+C 置 running=false)
|
||||||
|
// 能在超时后被检查到,避免永久阻塞等待下一条消息。
|
||||||
|
let envelope = match self.rx.recv_timeout(std::time::Duration::from_millis(200)) {
|
||||||
Ok(env) => env,
|
Ok(env) => env,
|
||||||
Err(_) => {
|
Err(mpsc::RecvTimeoutError::Timeout) => continue,
|
||||||
|
Err(mpsc::RecvTimeoutError::Disconnected) => {
|
||||||
println!("[ServiceManager] 所有发送端已关闭,退出");
|
println!("[ServiceManager] 所有发送端已关闭,退出");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -763,6 +766,7 @@ impl ServiceManager {
|
|||||||
Message::Shutdown => {
|
Message::Shutdown => {
|
||||||
println!("[ServiceManager] 收到 Shutdown 指令");
|
println!("[ServiceManager] 收到 Shutdown 指令");
|
||||||
self.broadcast_message(Message::Shutdown);
|
self.broadcast_message(Message::Shutdown);
|
||||||
|
self.running = false;
|
||||||
}
|
}
|
||||||
Message::WifiResult(payload) => {
|
Message::WifiResult(payload) => {
|
||||||
self.broadcast_message(Message::WifiResult(payload));
|
self.broadcast_message(Message::WifiResult(payload));
|
||||||
|
|||||||
@@ -113,10 +113,17 @@ fn main() -> Result<()> {
|
|||||||
// 设置 Ctrl+C 信号处理
|
// 设置 Ctrl+C 信号处理
|
||||||
let running = Arc::new(AtomicBool::new(true));
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
let r = running.clone();
|
let r = running.clone();
|
||||||
|
let shutdown_tx = manager.sender();
|
||||||
|
|
||||||
ctrlc::set_handler(move || {
|
ctrlc::set_handler(move || {
|
||||||
println!("\n收到退出信号,正在关闭...");
|
println!("\n收到退出信号,正在关闭...");
|
||||||
r.store(false, Ordering::SeqCst);
|
r.store(false, Ordering::SeqCst);
|
||||||
|
// 注入 Shutdown 消息,唤醒主消息循环并触发优雅停机
|
||||||
|
let _ = shutdown_tx.send(showen_v2::core::message::Envelope {
|
||||||
|
from: "signal".to_string(),
|
||||||
|
to: showen_v2::core::message::Destination::Manager,
|
||||||
|
message: showen_v2::core::message::Message::Shutdown,
|
||||||
|
});
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
println!("启动所有插件...");
|
println!("启动所有插件...");
|
||||||
|
|||||||
Reference in New Issue
Block a user