Skip to content

lock: taking over a stale FileLock is racy, so several processes can hold the writer lock at once #2979

Open

Description

@inth3shadows

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).

Activity

  1. vedantb7 commented on Oct 28, 2026

    @vedantb7

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions