Goal
State files written with bare std::fs::write corrupt on partial-write (crash, OOM, SIGKILL). Provide an atomic-write bridge and migrate every state-file writer to use it.
Sub-issue of #844.
Bridge API
fbuild_core::fs::write_atomic(path: impl AsRef<Path>, content: impl AsRef<[u8]>) -> Result<()> that:
- Writes content to
<path>.tmp.<pid>.<nonce>.
- Calls
File::sync_all() to flush the write.
- Atomically renames to the final path.
- On Windows, uses
MoveFileExW with MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH.
Migration targets (HIGH risk: corruption blocks rebuilds)
crates/fbuild-build/src/build_info.rs:291 — std::fs::write(path, &json) (build fingerprint JSON)
crates/fbuild-packages/src/toolchain/esp32_metadata.rs:236,247,273,283 — framework discovery cache JSONs
crates/fbuild-cli/src/cli/symbols_cmd.rs:180 — symbol dump
crates/fbuild-cli/src/cli/clang_tools.rs:206 — IWYU database
crates/fbuild-cli/src/cli/clangd_config.rs:87 — IDE config
Already correct (do not touch)
crates/fbuild-daemon/src/status_manager.rs:211 — already uses tempfile + rename pattern (the reference implementation).
Lint
After the migration: ban std::fs::write in code paths that touch known-state-file glob patterns? Probably not — too many false positives. Better: code review checklist + audit on review of any new state file.
Acceptance
References: #844.
Goal
State files written with bare
std::fs::writecorrupt on partial-write (crash, OOM, SIGKILL). Provide an atomic-write bridge and migrate every state-file writer to use it.Sub-issue of #844.
Bridge API
fbuild_core::fs::write_atomic(path: impl AsRef<Path>, content: impl AsRef<[u8]>) -> Result<()>that:<path>.tmp.<pid>.<nonce>.File::sync_all()to flush the write.MoveFileExWwithMOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH.Migration targets (HIGH risk: corruption blocks rebuilds)
crates/fbuild-build/src/build_info.rs:291—std::fs::write(path, &json)(build fingerprint JSON)crates/fbuild-packages/src/toolchain/esp32_metadata.rs:236,247,273,283— framework discovery cache JSONscrates/fbuild-cli/src/cli/symbols_cmd.rs:180— symbol dumpcrates/fbuild-cli/src/cli/clang_tools.rs:206— IWYU databasecrates/fbuild-cli/src/cli/clangd_config.rs:87— IDE configAlready correct (do not touch)
crates/fbuild-daemon/src/status_manager.rs:211— already uses tempfile + rename pattern (the reference implementation).Lint
After the migration: ban
std::fs::writein code paths that touch known-state-file glob patterns? Probably not — too many false positives. Better: code review checklist + audit on review of any new state file.Acceptance
fbuild_core::fs::write_atomic()exists with tests covering crash-mid-write recoverystatus_manager.rs:210-225refactored to call the shared helper (deduplication)References: #844.