diff --git a/apps/ai-game-creator-shell/src-tauri/src/export/registry.rs b/apps/ai-game-creator-shell/src-tauri/src/export/registry.rs index 7033e8c9c..569758eb9 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/export/registry.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/export/registry.rs @@ -8,6 +8,7 @@ use std::fmt; use std::fs; use std::io::Write as _; use std::path::{Path, PathBuf}; +use std::sync::atomic::Ordering; use serde::de::DeserializeOwned; use serde::Serialize; @@ -150,9 +151,18 @@ fn temp_path(path: &Path) -> PathBuf { .file_name() .map(|name| name.to_string_lossy().into_owned()) .unwrap_or_else(|| "registry.json".to_string()); - path.with_file_name(format!(".{file_name}.{}.tmp", std::process::id())) + // 临时文件名必须**每次写都不同**:只用 pid 的话,同一进程里两个并发写共用同一个临时文件, + // 一个会截断另一个正在写的内容,rename 也会互相抢。进程内原子计数器保证不重名。 + let sequence = TEMP_FILE_SEQUENCE.fetch_add(1, Ordering::Relaxed); + path.with_file_name(format!( + ".{file_name}.{}.{sequence}.tmp", + std::process::id() + )) } +/// 同进程内临时文件名的序号,见 [`temp_path`]。 +static TEMP_FILE_SEQUENCE: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); + #[cfg(test)] mod tests { use super::*;