fix: guard terminateStaleProcessesSync against non-ESRCH kill errors#109702
Conversation
The two catch blocks silently swallowed all errors, not just ESRCH. Non-ESRCH errors (e.g. EPERM) indicate the process is still alive but cannot be signaled — continuing as if it were killed risks leaving a stale process on the port. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
|
Codex review: needs real behavior proof before merge. Reviewed July 17, 2026, 2:11 AM ET / 06:11 UTC. Summary PR surface: Source +6, Tests +14. Total +20 across 2 files. Reproducibility: yes. at source level: with multiple stale PIDs, make an earlier SIGTERM succeed and a later process.kill throw EPERM; the new throw reaches the outer catch before escalation or waitForPortFreeSync. This was not executed as a live current-head reproduction. Review metrics: none identified. 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: Handle errors per PID: ignore ESRCH, retain observable diagnostics for other errors, continue safe cleanup of the remaining PIDs, and guarantee waitForPortFreeSync still executes; cover mixed-success multi-PID cases and demonstrate the result with redacted terminal proof. Do we have a high-confidence way to reproduce the issue? Yes at source level: with multiple stale PIDs, make an earlier SIGTERM succeed and a later process.kill throw EPERM; the new throw reaches the outer catch before escalation or waitForPortFreeSync. This was not executed as a live current-head reproduction. Is this the best way to solve the issue? No. ESRCH-specific classification is appropriate, but throwing from the private PID loop is not the narrowest safe fix because the outer best-effort wrapper suppresses the error and skips required cleanup completion. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against c80b236a09d6. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +6, Tests +14. Total +20 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
|
Co-authored-by: 丁宇婷0668001435 <[email protected]>
|
Merged via squash.
|
…penclaw#109702) * fix: guard terminateStaleProcessesSync against non-ESRCH kill errors The two catch blocks silently swallowed all errors, not just ESRCH. Non-ESRCH errors (e.g. EPERM) indicate the process is still alive but cannot be signaled — continuing as if it were killed risks leaving a stale process on the port. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix: continue stale PID cleanup after signal errors Co-authored-by: 丁宇婷0668001435 <[email protected]> --------- Co-authored-by: Claude Sonnet 4.6 <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
What Problem This Solves
terminateStaleProcessesSync()insrc/infra/restart-stale-pids.tshas two catch blocks afterprocess.kill()that silently swallow ALL errors, not just ESRCH. If a non-ESRCH error occurs (e.g. EPERM), the process is still alive but the code proceeds as if it were killed — potentially leaving a stale process on the port while waiting for the port to free.Same pattern as #109590 (gateway signal guard) and #109692 (port force-free guard).
Evidence
Tests
src/infra/restart-stale-pids.test.ts— 54 tests pass, including 1 new test:CI
Merge Risk
Low. +4 lines across two catch blocks inside a private function. Follows the established ESRCH-guard pattern already accepted in #109590.