Replace settings.json rather than rewriting it in place - #820
Merged
Conversation
Write deleted the file and then opened it again to serialise into, so between the two there was no settings.json at all, and until the serialise finished there was a partial one. A kill anywhere in there - a logoff, a reboot, task manager - left the tray meeting "Cannot start. Failed to read settings" at every launch afterwards, with deleting the file by hand the only way out. It is now serialised beside the file and moved over it, so the live path only ever holds a whole document. The swap can lose a race with anything holding the file open, which the old delete could not, so it is retried for a fifth of a second before giving up. That path used to throw straight out of an async void click handler. WriteFile is the file half on its own. Write also persists two User scope environment variables, a registry write and a broadcast each, which the test that hammers this would spend all its time on.
It reopened settings.json the instant it closed it, so it held the file for most of the time it ran. On the two core Windows runner that starved the swap of all eleven attempts it has and failed the test on the writer's side, which is the test being an adversary no real reader is. It now looks once a millisecond, and runs until it has looked a hundred times rather than for a fixed number of writes, so the number of independent samples does not depend on how fast the machine writes. A missing file is counted as a look too - without that the run ended on the write cap with too few looks to assert on, and the unfixed write failed on the guard rather than on what it was there to catch.
This was referenced Aug 26, 2026
This was referenced Aug 27, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Write deleted the file and then opened it again to serialise into, so between the
two there was no settings.json at all, and until the serialise finished there was a
partial one. A kill anywhere in there - a logoff, a reboot, task manager - left the
tray meeting "Cannot start. Failed to read settings" at every launch afterwards,
with deleting the file by hand the only way out.
It is now serialised beside the file and moved over it, so the live path only ever
holds a whole document.
The swap can lose a race with anything holding the file open, which the old delete
could not, so it is retried for a fifth of a second before giving up. That path used
to throw straight out of an async void click handler.
WriteFile is the file half on its own. Write also persists two User scope
environment variables, a registry write and a broadcast each, which the test that
hammers this would spend all its time on.