From ab1dd9160ccc7041e421b786b87001e1262739e7 Mon Sep 17 00:00:00 2001 From: pulsareonbot Date: Sat, 4 Jul 2026 12:22:51 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Ctrl+C=20=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E5=8F=8A=E6=97=B6=E9=80=80=E5=87=BA=E4=B8=BB=E5=BE=AA?= =?UTF-8?q?=E7=8E=AF=E7=9A=84=20P1=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: 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) 验证. --- src/core/service_manager.rs | 8 ++++++-- src/main.rs | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/core/service_manager.rs b/src/core/service_manager.rs index a877987..48d6e78 100644 --- a/src/core/service_manager.rs +++ b/src/core/service_manager.rs @@ -358,9 +358,12 @@ impl ServiceManager { self.running = true; 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, - Err(_) => { + Err(mpsc::RecvTimeoutError::Timeout) => continue, + Err(mpsc::RecvTimeoutError::Disconnected) => { println!("[ServiceManager] 所有发送端已关闭,退出"); break; } @@ -763,6 +766,7 @@ impl ServiceManager { Message::Shutdown => { println!("[ServiceManager] 收到 Shutdown 指令"); self.broadcast_message(Message::Shutdown); + self.running = false; } Message::WifiResult(payload) => { self.broadcast_message(Message::WifiResult(payload)); diff --git a/src/main.rs b/src/main.rs index e62c8b8..5562f84 100644 --- a/src/main.rs +++ b/src/main.rs @@ -113,10 +113,17 @@ fn main() -> Result<()> { // 设置 Ctrl+C 信号处理 let running = Arc::new(AtomicBool::new(true)); let r = running.clone(); + let shutdown_tx = manager.sender(); ctrlc::set_handler(move || { println!("\n收到退出信号,正在关闭..."); 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!("启动所有插件...");