Skip to content

fix(site-memory): stop a stale file lock from being stolen while the owner is still alive - #496

Open
Agnik47 wants to merge 1 commit into
agentrhq:mainfrom
Agnik47:fix/432-file-lock-liveness
Open

fix(site-memory): stop a stale file lock from being stolen while the owner is still alive#496
Agnik47 wants to merge 1 commit into
agentrhq:mainfrom
Agnik47:fix/432-file-lock-liveness

Conversation

@Agnik47

@Agnik47 Agnik47 commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Bug

breakIfAbandoned() in src/site-memory/file-lock.ts decided a lock was abandoned using only two signals: the lock file's mtime is older than staleMs, OR the owning pid is confirmed dead. It did not check whether the owning process was actually still alive and working.

If a critical section legitimately runs longer than staleMs (big file, slow disk, loaded machine), a second process concludes the first one crashed, deletes its lock file, and starts its own critical section while the first is still running. Both writers race the same file, and whichever rename() lands last silently discards the other's work.

Fix

breakIfAbandoned() now checks owner liveness first: if the owning pid is checkable and confirmed alive on the same host (process.kill(pid, 0)), the lock is never broken on staleness alone. This is decisive, not just one of two OR'd signals. Locks whose owner is confirmed dead, or whose owner can't be checked (cross-host), still fall back to the existing stale-timeout behavior.

Testing

Added two regression tests in file-lock.test.ts:

  • does not steal a stale lock from a same-host owner that is still alive — a backdated lock file owned by a live pid must still report SITE_MEMORY_BUSY rather than being silently taken over.
  • does not let two critical sections overlap when one runs longer than staleMs — reproduces the exact race from the issue: two withFileLock calls where the first's section outlives staleMs.

Both fail against the pre-fix code and pass with the fix. Full file-lock.test.ts suite: 9/9 passing. npm run typecheck clean.

Fixes #432

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_018qEzPWwgbBFci2RcjPAhMn

🤖 Generated with Claude Code

https://claude.ai/code/session_018qEzPWwgbBFci2RcjPAhMn

…owner is still alive

breakIfAbandoned() broke a lock whenever it was older than staleMs,
regardless of whether the owning process was still running its critical
section. A same-host owner confirmed alive by process.kill(pid, 0) is now
decisive: staleness alone never steals its lock, only a confirmed-dead
owner or an unverifiable (cross-host) owner does.

Fixes agentrhq#432

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qEzPWwgbBFci2RcjPAhMn
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

🟠 Maintainer review suggested — low confidence

The automated review could not reach a fully supported conclusion.

Limitations

  • The automated review returned an invalid structured result.

This review is advisory and does not block merging.

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.

site-memory file lock breaks mutual exclusion when a critical section runs longer than staleMs

1 participant