fix(session): add fallback lock file cleanup on session write-lock release#91332
fix(session): add fallback lock file cleanup on session write-lock release#91332immortal-autumn wants to merge 2 commits into
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed June 30, 2026, 3:35 PM ET / 19:35 UTC. Summary PR surface: Source +17. Total +17 across 1 file. Reproducibility: yes. at source level. Review metrics: 1 noteworthy metric.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Make any release-side fallback cleanup ownership-safe at the deletion point or snapshot/token-aware, add a focused regression for same-process reacquire during cleanup, and require redacted runtime proof or explicit maintainer proof override before merge. Do we have a high-confidence way to reproduce the issue? Yes, at source level. Is this the best way to solve the issue? No. The PR is a plausible mitigation, but the best fix must preserve mutual exclusion with a deletion-point ownership check or snapshot/token-aware cleanup plus focused regression coverage and proof. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 5a89484eb31d. Label changesLabel justifications:
Evidence reviewedPR surface: Source +17. Total +17 across 1 file. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8ada369b4f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const payload = await readLockPayload(lockPath); | ||
| if (payload?.pid === process.pid) { | ||
| await fs.rm(lockPath, { force: true }); |
There was a problem hiding this comment.
Preserve active reentrant locks on release
When the same process holds a reentrant session write lock (for example allowReentrant: true, or the watchdog test's old release handle after a new in-process lock is acquired), innerRelease() can legitimately leave the .lock file in place because another in-process holder still owns it. This fallback then sees the current PID and removes that active lock file anyway, so another writer can acquire the session while the second holder still believes it is protected; the existing expectLockRemovedOnlyAfterFinalRelease coverage in src/agents/session-write-lock.test.ts exercises exactly this contract but cannot pass with this unconditional cleanup.
Useful? React with 👍 / 👎.
When sidecar-lock's removeLockIfUnchanged fails due to snapshot mismatch (e.g. lock file content modified between acquire and release), the session write-lock file persists on disk, blocking all subsequent messages to that session with SessionWriteLockTimeoutError. This adds a fallback cleanup in acquireSessionWriteLock: after the inner release, check if the lock file still exists and its pid matches the current process. If so, force-remove it. Fixes session write lock leak observed when embedded abort settle times out during cleanup, leaving the lock file orphaned on disk with maxHoldMs=1020000 (17 min) and no automatic recovery. Closes openclaw#91327
The original fallback unconditionally force-removed the lock file whenever pid matched, which broke reentrant lock semantics — the first release in a reentrant pair would remove the file while another holder still expected it to exist. Now checks sessionLockHeldByThisProcess before the fallback cleanup. If any reentrant holder remains, the lock file is preserved as sidecar-lock intends.
Real behavior proof — maintainer judgement requestedThe "Real behavior proof" CI gate is asking for runtime evidence from a live OpenClaw setup. I want to be transparent about what has been verified and what requires maintainer judgement: ✅ Verified
❌ Cannot reproduce in test environmentThe original bug (sidecar-lock snapshot mismatch leaving orphan 🔧 RequestGiven that this fix is defensive (no existing code path is broken), test-verified for the reentrancy edge case, and the original bug requires a production gateway to reproduce, I respectfully request maintainer review on whether a If a more concrete runtime verification is preferred, I am happy to set up a local gateway instance with this patch and capture logs — just let me know the preferred format. |
|
This pull request has been automatically marked as stale due to inactivity. |
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: fix(session): add fallback lock file cleanup on session write-lock release This is item 1/1 in the current shard. Shard 0/2. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
Problem
When
sidecar-lock'sremoveLockIfUnchangedfails because the lock file snapshot doesn't match (content/inode changed between acquisition and release), the session write-lock file persists on disk permanently. This blocks all subsequent messages to that session withSessionWriteLockTimeoutErroruntil the gateway is restarted.Observed in production (OpenClaw 2026.6.1):
See #91327 for full root cause analysis.
Fix
Add a fallback cleanup in
acquireSessionWriteLockinsession-write-lock.ts: after the inner sidecar-lockrelease()completes, check if the.lockfile still exists on disk and no reentrant holder remains. If both conditions hold and the file'spidfield matches the current process, force-remove it.Why this is safe
sessionLockHeldByThisProcess()prevents removing the lock file while other reentrant holders still expect it to exist.process.pid. If another process replaced the lock file, it won't match → we don't touch it.release()still runs as before. This is purely additive cleanup.Files changed
src/agents/session-write-lock.ts: +18 lines, 1 changedReal behavior proof
Setup:
openclaw/maintip — previously was 4,466 commits behind, now cleanly atop current upstreamVerified before push:
Reentrancy fix (v2): First iteration broke
expectLockRemovedOnlyAfterFinalRelease— the fallback removed the lock file during the first release in a reentrant pair. AddedsessionLockHeldByThisProcess()guard so the fallback only triggers when all holders have released.Scope check —
readLockPayload,lockPath,fs,process.pid,normalizedSessionFile, andsessionLockHeldByThisProcessare all in scope at the fix site.CI: Full test suite running.
Not tested (requires production environment):