You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
lock: taking over a stale FileLock is racy, so several processes can hold the writer lock at once #2979
FileLock's takeover of a stale lock isn't atomic, so several processes that start at once after a crash can all believe they hold the writer lock.
utils.ts#L283-L312: read the PID, see it is dead, unlinkSync, then writeFileSync(..., { flag: 'wx' }). Process A unlinks the stale file and creates its own. Process B, which read the same dead PID a moment earlier, then unlinks A's lock and creates its own, and both return from acquire().
Repro: a lock file containing a dead PID (999999). 8 processes call new FileLock(lock).acquire() at the same instant, and a holder records its PID and keeps the lock for 300 ms.
rounds with >1 holder: 8/15 (up to 3 simultaneous holders)
Reproduced on main at 77ee348, Linux/WSL2, Node 22.23.2, CODEGRAPH_KERNEL=0.
When it bites. After a crash or kill, the MCP watcher, a git hook and the CLI often start together. Each then writes to the index as the "only" writer.
Expected. Make the takeover atomic. For example, write the new PID to a temp file and rename/link it over the lock only if the lock still holds the stale PID you read, or take the lock with an exclusive open on a second sentinel during takeover, so that exactly one process can replace a stale lock.
Related: #1959 / #1978 (a live holder's lock going stale; ownership, not this race).
I’ve investigated this issue and reproduced the stale-lock takeover race under multi-process contention. I’m working on a fix and a regression test to ensure that concurrent processes cannot take over the same stale lock.
Activity
vedantb7 commentedon Oct 28, 2026
I’ve investigated this issue and reproduced the stale-lock takeover race under multi-process contention. I’m working on a fix and a regression test to ensure that concurrent processes cannot take over the same stale lock.