fix: force-release session .jsonl.lock on dispose when retained-lock user is stuck#95854
fix: force-release session .jsonl.lock on dispose when retained-lock user is stuck#95854joelnishanth wants to merge 2 commits into
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed June 23, 2026, 12:19 PM ET / 16:19 UTC. Summary PR surface: Source +42, Tests +35. Total +77 across 2 files. Reproducibility: yes. Source inspection on current main shows a retained Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. 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: Keep the stale-lock recovery, but preserve or explicitly product-approve the active-writer safety invariant before merge, then add focused regression coverage plus redacted live/runtime proof of session recovery. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection on current main shows a retained Is this the best way to solve the issue? No, not yet. The patch targets the right owner path for the stale lock, but treating a slow retained writer as dead after 5 seconds conflicts with the existing active-writer invariant and the sidecar-lock recovery contract unless maintainers explicitly accept that terminal cleanup tradeoff. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 9ff7abc8989c. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +42, Tests +35. Total +77 across 2 files. 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
|
|
Thanks for taking this on. I rebased and reviewed this against latest I'm closing this PR rather than proceed with the force-release approach. The concern is that releasing the physical #96100 has now merged and addresses the retained-lock abort cleanup path we believe was gating #95833. We’ll keep #95833 open while the reporter validates whether that fully resolves the stale lock / heap growth behavior. Thanks again for this contribution! |
Closes #95833
What Problem This Solves
Fixes an issue where sessions would permanently break with "Something went wrong" after a subagent abort-settle timeout, because the
.jsonl.lockfile was never released. Users had to manually delete the lock file to restore the session.Why This Change Was Made
disposeHeldLockAfterRetainedIdle()is the final lock cleanup path called from the attempt's outerfinallyblock. Previously, whenwaitForRetainedLockIdle()returnedfalse(caller inside an active write-lock scope) or waited indefinitely (a stuck operation never released its retained lock), dispose would return without releasing the physical lock — leaving a stale.jsonl.lockthat blocked the session permanently.The fix introduces a bounded variant
waitForRetainedLockIdleWithTimeout()that adds a 5-second timeout to the retained-lock-idle wait. If the wait returnsfalse(either because the caller is inside an active write-lock scope or the timeout fires), dispose now force-releases the lock anyway — since dispose is the final cleanup path and no more writes will happen.User Impact
Sessions that previously required manual
.jsonl.lockremoval after subagent abort-settle timeouts now recover automatically. The session lock is always released on every exit path of the attempt lifecycle.Evidence
Test:
pnpm test -- src/agents/embedded-agent-runner/run/attempt.session-lock.test.tsRegression test: The new test
force-releases on dispose when retained-lock user is stuck (#95833)simulates a stuckwithSessionWriteLockcallback that never completes (like a hung model call). It verifies thatdispose()force-releases the physical lock after the 5-second timeout instead of hanging indefinitely.All related tests pass:
— Joel Nishanth · offlyn.AI