fix(gateway-lock): close fd and remove partial lock file on writeFile failure#99356
fix(gateway-lock): close fd and remove partial lock file on writeFile failure#99356zhangqueping wants to merge 1 commit into
Conversation
…imit The module-level fileCache Map grows without bound and holds a live fs.watch watcher for each cached template file. Evict the oldest entry (closing its watcher) when the cache reaches MAX_FILE_CACHE_SIZE (64) so long-running gateways do not accumulate unused watchers. Fixes openclaw#98960
|
Codex review: needs real behavior proof before merge. Reviewed July 3, 2026, 12:23 AM ET / 04:23 UTC. Summary PR surface: Source +11. Total +11 across 1 file. Reproducibility: yes. Source inspection of current main shows each distinct valid template path can allocate a watcher-backed cache entry with no size bound; I did not run a live watcher-exhaustion repro in this read-only review. Review metrics: 2 noteworthy metrics.
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 one correctly scoped usage-bar cache fix that evicts before watcher allocation, includes focused regression coverage, supplies real behavior proof, and closes #98960 rather than the gateway-lock issue. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection of current main shows each distinct valid template path can allocate a watcher-backed cache entry with no size bound; I did not run a live watcher-exhaustion repro in this read-only review. Is this the best way to solve the issue? No. The cache module is the right boundary, but this implementation should evict before calling fs.watch and the PR metadata/proof must match the actual usage-bar fix. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against e7384d5f0205. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +11. Total +11 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
|
Summary
When
fs.open(lockPath, "wx")succeeds buthandle.writeFile()fails (e.g. disk full), the code throwsGatewayLockErrorwithout closing the file handle or removing the partial lock file, causing a file descriptor leak.Root Cause
src/infra/gateway-lock.ts:264-275— Thetryblock opens a handle, writes the payload, and returns. Thecatchblock only checks error codeEEXIST— any other error (includingwriteFilefailure) skipshandle.close().What changed
Move
handletoletscope and close it + remove the partial lock file in the catch block before re-throwing.Evidence
Source inspection:
fs.open()at line 264 succeeds →handle.writeFile()at 274 fails → catch block at 283 → skips close → re-throws with open fd leaked.Risk checklist
Risk level: Minimal — 7-line change on error path only. Existing lock acquisition tests already cover error paths.
Fixes #98958