fix: prevent file corruption when multiple IDE windows patch concurrently#12
Open
BenKalsky wants to merge 4 commits into
Open
fix: prevent file corruption when multiple IDE windows patch concurrently#12BenKalsky wants to merge 4 commits into
BenKalsky wants to merge 4 commits into
Conversation
… directory naming convention
Drop CLAUDE.md, .claude/, *.code-workspace, llms*.txt, vsix and other dev-only files from the published extension package (16 -> 10 files). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ntly Each open IDE window runs its own extension host, and they all patch the same Claude Code files on disk. Their backup/read/write cycles could interleave and truncate a file — in one report webview/index.js shrank from 4.8 MB to ~1 MB, leaving the Claude panel blank. Injection is now: - Serialized via a per-extension-directory lock file (stale locks are auto-broken; never hangs the extension). - Atomic — written to a temp file and renamed into place, so a reader never sees a half-written file. - Guarded — a result smaller than the pristine backup is rejected instead of written, so truncation is never persisted. Public entry points are thin lock-serialized wrappers over lock-free *Impl functions, so fixBidi can compose them without deadlocking. Adds a concurrency regression test (npm test) that patches one extension from 8 simulated windows at once. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Problem
Each open IDE window runs its own extension host, and they all patch the same Claude Code files on disk (
webview/index.js,webview/index.css,extension.js). The injection path does an unsynchronized read-modify-write (copyFilebackup →readFile→writeFile) with no lock between windows/processes.With more than one window open, these cycles interleave and tear the file. In a real report on Antigravity IDE,
webview/index.jswas truncated from 4.8 MB → ~1 MB right after a Claude Code reinstall (which re-triggered patching in every window). The truncated webview bundle fails to load → the Claude panel renders completely blank and sessions appear gone. Restoring from the.bakbrought it back, confirming the on-disk file was the corrupted artifact.This is separate from #11 (which fixes which directory is searched); this fixes how the files are written.
Fix
src/injector.ts:withFileLock), so only one window patches at a time. Stale locks (crashed window) are auto-broken after 30s, and it falls through after a bounded wait rather than ever hanging the extension.atomicWrite): write to a unique temp file thenrename()into place, so a reader/racing window never observes a half-written file.addRtl,addRtlAlways,addRtlAuto,fixBidi,removeRtl) are now thin lock-serialized wrappers over lock-free*Implfunctions, sofixBidicomposes them without re-entrant deadlock.Test
Adds
test/concurrency.test.cjs(run withnpm test): patches one extension from 8 simulated windows concurrently and asserts no truncation, no stacked injections, pristine backups, and clean removal. The pre-fix code truncates/hangs under the same race; the fixed code passes.Verified:
tsc --noEmitclean,npm run buildclean,npm testpasses. Bumped to v0.4.2.🤖 Generated with Claude Code