fix(demo): report a failed cleanup and stop the writer that most likely raced it - #1166
Merged
Merged
Conversation
…kely raced it The crash-cleanup test went red once in CI naming a leftover `commitlore-demo-*` directory, passed on a re-run of the same commit, and passed on the other node leg of the same run. Nothing said why: `cleanup` caught the `rmSync` error and discarded it, so the one occurrence carried no errno, and a race, a permission and a full disk were indistinguishable from each other and from a removal that never ran. Three changes, in order of what they are worth: - The failure is reported — the directory and the reason, on stderr, never rethrown. `cleanup` also runs from a signal handler, where a throw has nowhere to go, and on the crash path it must not mask the error it is unwinding. - The demo's repository sets `gc.auto=0` and `maintenance.auto=false`, so `git commit` cannot leave background maintenance writing inside a directory that is about to be removed. That is the mechanism the occurrence is most consistent with, and a throwaway repository should not start one regardless. - `rmSync` gets `maxRetries`, which covers the errno set a concurrent writer produces. What this does not do is prove the cause. The new test injects the failure through a mocked `rmSync` because a real race is not reliably reproducible, so what it pins is the reporting: a cleanup that fails names the path and the errno. The next occurrence will say what this one could not. Limit: the evidence is one CI occurrence that passed on re-run and on the other node leg of the same run, so the cause was never observed Ruled-out: waiting for a reproduction before changing anything | a real removal race is not reliably reproducible, and the discarded errno is the reason the one occurrence could not be read at all Ruled-out: calling the retry a root fix | a retry makes a race survivable without showing that a race is what happened, and the cause is still unobserved Ruled-out: failing the command when cleanup fails | a leftover temporary directory is a leak, and a non-zero exit would make `commitlore demo` fail for something the user cannot act on Warn: the new test injects the failure through a mocked `rmSync`, so it pins the reporting and not the cause; if this goes red again the stderr line carries the errno -- read it before changing anything else Blast: local Undo: easy Certainty: tentative Unverified: whether background maintenance was the writer; the repository config change removes that mechanism and nothing observed it happening Record-Id: r-cleanupreport1163 Provenance: drafted
CommitLore — record lintTrailers: clean — 1 commit in Active constraints for the paths this PR touchesLimits (5)
Ruled out (10)
Warnings (2)
Trailer violations fail this check. Active constraints are informational — they are what the repository already decided, not a verdict on this PR. |
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.
Closes #1163
What the evidence was
One CI occurrence:
check (24)on the canonical pull request for #1154,test/demo.test.ts > temporary directory is gone after a simulated crash,naming a leftover
commitlore-demo-*directory.check (22.23.2)passed in thesame run, re-running the failed job on the same commit passed, and the full
suite passed locally on that commit.
And nothing said why.
cleanupcaught thermSyncerror and discarded it, sothat occurrence carried no errno — a race, a permission, and a full disk were
indistinguishable from each other and from a removal that never ran.
The change
rethrown:
cleanupalso runs from a signal handler, where a throw hasnowhere to go, and on the crash path it must not mask the error it is
unwinding.
Error.messagefromfsalready carries the errno and thesyscall, which is the part that says what kind of failure it was.
gc.auto=0andmaintenance.auto=false, sogit commitcannot leavebackground maintenance writing inside a directory about to be removed. A
throwaway repository should not start one regardless.
rmSyncgetsmaxRetries, which covers the errno set a concurrentwriter produces (
EBUSY,ENOTEMPTY,EPERM, …).What this does not claim
It does not prove the cause, and the commit record says so —
Unverified:whether background maintenance was the writer,
Certainty: tentative, andRuled-out: calling the retry a root fix | a retry makes a race survivable without showing that a race is what happened.Verification
reports a cleanup failure instead of discarding it (bug-issue-1163). The failure is injected through a mockedrmSync, becausea real race is not reliably reproducible and a test that waited for one would
be the flake it is meant to explain. It asserts the stderr line names the
directory and
EACCES, that the simulated crash error still reaches thecaller, and — as arrival — that the injection really did stop the removal.
gc.autoandmaintenance.autooff the directorythe failed cleanup left behind, so the config claim is checked against the
repository the demo actually built.
expected '' to contain 'could not remove'; without the config thegit config --get gc.autolookup fails. Both halves are load-bearing.tsc --noEmitclean.dist/is absent on purpose:canonical-merge.ymlrebuilds it and regeneratesthe manifest.