From 232d74b617a961e7541df52068f5d996eabcb000 Mon Sep 17 00:00:00 2001 From: Yuyi-Oak <1722157266@qq.com> Date: Thu, 16 Jul 2026 09:38:46 -0700 Subject: [PATCH] =?UTF-8?q?fix(daemon):=20=E4=B8=B2=E8=A1=8C=E5=8C=96=20ba?= =?UTF-8?q?t-status.json=20=E7=9A=84=E8=AF=BB-=E6=94=B9-=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit watch 循环线程(update_daemon_status/update_daemon_progress)与 RPC 处理线程 (update_daemon_state_only)都会对状态文件做“读→改字段→写回”。单次写虽原子, 但整段读-改-写非原子,无互斥时并发线程会 last-writer-wins 丢失对方的字段更新。 新增进程级 DAEMON_STATUS_FILE_LOCK,三处读-改-写函数入口统一获取该锁串行化 (锁中毒时取 into_inner 继续,不 panic)。 对应 issue #18 维护清单 3-4。 Co-Authored-By: Claude Fable 5 --- infrastructure/src/bin/bat_official_sync.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/infrastructure/src/bin/bat_official_sync.rs b/infrastructure/src/bin/bat_official_sync.rs index 47943eb..1be917d 100644 --- a/infrastructure/src/bin/bat_official_sync.rs +++ b/infrastructure/src/bin/bat_official_sync.rs @@ -3042,6 +3042,19 @@ fn read_daemon_status_file(path: &Path) -> anyhow::Result = Mutex::new(()); + +fn lock_daemon_status_file() -> std::sync::MutexGuard<'static, ()> { + DAEMON_STATUS_FILE_LOCK + .lock() + .unwrap_or_else(|poison| poison.into_inner()) +} + fn write_daemon_status_file(path: &Path, status: &DaemonStatusFile) -> anyhow::Result<()> { write_file_atomic( path, @@ -3054,6 +3067,7 @@ fn write_daemon_status_file(path: &Path, status: &DaemonStatusFile) -> anyhow::R } fn update_daemon_status(state_dir: &Path, update: DaemonStatusUpdate<'_>) -> anyhow::Result<()> { + let _guard = lock_daemon_status_file(); let status_path = daemon_status_path(state_dir); let mut status = read_daemon_status_file(&status_path)?.unwrap_or_else(|| DaemonStatusFile { version: DAEMON_STATUS_VERSION, @@ -3099,6 +3113,7 @@ fn update_daemon_status(state_dir: &Path, update: DaemonStatusUpdate<'_>) -> any } fn update_daemon_progress(state_dir: &Path, event: &OfficialUpdateProgress) -> anyhow::Result<()> { + let _guard = lock_daemon_status_file(); let status_path = daemon_status_path(state_dir); let Some(mut status) = read_daemon_status_file(&status_path)? else { return Ok(()); @@ -3128,6 +3143,7 @@ fn update_daemon_progress(state_dir: &Path, event: &OfficialUpdateProgress) -> a } fn update_daemon_state_only(state_dir: &Path, state: &str) -> anyhow::Result<()> { + let _guard = lock_daemon_status_file(); let status_path = daemon_status_path(state_dir); let Some(mut status) = read_daemon_status_file(&status_path)? else { return Ok(());