-
Notifications
You must be signed in to change notification settings - Fork 30
fix: atomic config writes (no more truncated JSON on crash) #252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| using System.IO; | ||
|
|
||
| namespace PlanViewer.App.Services; | ||
|
|
||
| /// <summary> | ||
| /// Helper for atomic text-file writes: write to a sibling .tmp and rename | ||
| /// into place so a crash mid-write can't truncate the target file. Callers | ||
| /// are responsible for creating the parent directory first. | ||
| /// </summary> | ||
| internal static class AtomicFile | ||
| { | ||
| /// <summary> | ||
| /// Writes <paramref name="contents"/> to <paramref name="path"/> atomically | ||
| /// with respect to process crashes. If the process dies before the rename, | ||
| /// <paramref name="path"/> keeps its previous contents and a stray | ||
| /// <c>.tmp</c> sibling is left behind (cleaned up on the next call). | ||
| /// </summary> | ||
| public static void WriteAllText(string path, string contents) | ||
| { | ||
| var tmp = path + ".tmp"; | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: two processes calling Generated by Claude Code |
||
| File.WriteAllText(tmp, contents); | ||
| // File.Move with overwrite:true maps to MoveFileEx(MOVEFILE_REPLACE_EXISTING) | ||
| // on Windows and rename(2) on Unix — both atomic when source and destination | ||
| // live on the same filesystem, which is always the case here. | ||
| File.Move(tmp, path, overwrite: true); | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Scope caveat vs. the PR description: this closes the process-crash truncation hole (good — that's the bug that was actually hitting users), but it does not survive power loss. Generated by Claude Code |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: this file already has
using PlanViewer.App.Services;at line 18, so theServices.qualifier is redundant. The other three call sites in the PR use the unqualifiedAtomicFile.WriteAllText(...)— consistent to dropServices.here too.Generated by Claude Code