Skip to content

fix(git): stop leaking temp files when the cache write fails - #564

Merged
sirmalloc merged 2 commits into
sirmalloc:mainfrom
niklasgs:fix/git-cache-tmp-leak
Sep 3, 2026
Merged

fix(git): stop leaking temp files when the cache write fails#564
sirmalloc merged 2 commits into
sirmalloc:mainfrom
niklasgs:fix/git-cache-tmp-leak

Conversation

@niklasgs

@niklasgs niklasgs commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Fixes #563

writePersistentCache never deleted its temp file when the rename over the cache path failed, leaking one uniquely named .tmp per cache write (~400k observed on Windows, where EPERM from a scanner/sync client holding a handle is common).

Fix:

  • Unlink the temp file on failure, mirroring config.ts:writeSettingsJson (minus the rethrow — this cache is best-effort).
  • Stable temp name (<cachePath>.tmp) instead of pid+timestamp: the same held handle can defeat the unlink too, so reuse bounds the worst case to one orphan per repo that the next write truncates. A torn concurrent write reads as malformed JSON, which is already treated as a cache miss.
  • Regression test (fails without the fix): forces the rename to fail and asserts no .tmp is left behind.

Deliberately no sweep of pre-existing orphans — a readdir over a 400k-entry directory on the render path costs more than it saves. Affected users: delete ~/.cache/ccstatusline/git-cache/ once; it regenerates.

bun run lint clean, 1869 tests pass.

writePersistentCache wrote a uniquely named .tmp file and renamed it over
the cache path inside a swallow-all catch. When the write or rename fails
(notably EPERM on Windows while a virus scanner or sync client holds a
handle), the temp file was never unlinked, leaking one file per cache
write - observed at ~400k orphaned files in ~/.cache/ccstatusline/git-cache.

Clean up the temp file on failure, mirroring config.ts:writeSettingsJson
minus the rethrow since this cache is best-effort. Because the same held
handle can make the cleanup unlink fail too, the temp name is now stable
(cachePath + '.tmp') instead of unique: the worst case becomes a single
orphan per repo that the next write truncates. A torn concurrent write
only produces malformed JSON, which readPersistentCache already treats
as a cache miss.

Deliberately no sweep for pre-existing orphans: a readdir over a directory
that large on the render path costs more than it saves. Deleting the
git-cache directory once by hand is enough - it regenerates itself.
@niklasgs
niklasgs force-pushed the fix/git-cache-tmp-leak branch from 18dbbab to de0c9c6 Compare August 28, 2026 06:56
@sirmalloc
sirmalloc merged commit 237bdd7 into sirmalloc:main Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Git cache leaks .tmp files (~400k orphans observed on Windows)

2 participants