fix(run): close the run WebSocket on all exit paths of local --wait (BE-3404)#563
fix(run): close the run WebSocket on all exit paths of local --wait (BE-3404)#563mattmillerai wants to merge 1 commit into
Conversation
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 59 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
There was a problem hiding this comment.
🔍 Cursor Review — Consolidated panel
Triggered by @mattmillerai.
Judge call failed (status=parse_error): Could not parse JSON findings from output. First 500 chars:
I've verified the code structure. Let me confirm the exact placement of the `execution` assignment relative to the `try` block.
The key facts:
- Line 255: `execution = WorkflowExecution(...)` — assigned **unconditionally**, before the `try`.
- Line 269: `try:` begins.
- Lines 443–449: `finally:` block calls `_safe_close(execution)`.
The single panel finding (gemini-3.1-pro edge-case) claims `execution` could be `UnboundLocalError` in the `finally` if an exception/return happens "during early a
Re-trigger by removing and re-adding the cursor-review label.
ELI-5
When you run
comfy run --waitagainst a local ComfyUI server, the CLI opens a WebSocket to watch the job. On the happy path that socket was never explicitly closed — it lingered open (holding a server-side ws session) until the Python interpreter tore down at exit. This adds a best-effort close in the function's existingfinally:block so the socket is shut on every exit path — success, error, or interrupt.What & why
On the local
comfy run --waitsuccess path, the WebSocket opened byexecution.connect()was only closed via the SIGINT cancellation token (token.on_cancel(lambda: _safe_close(execution))). Afterwatch_execution()returned and the terminal envelope was emitted, the socket stayed open until interpreter teardown — a resource-hygiene defect surfaced during BE-3354.The fix adds
_safe_close(execution)to theexecute()finally:block (which already stops the Rich progress):Why it's safe
executionis constructed before thetry:, so it is always bound whenfinallyruns._safe_close(inexecution.py) already guardsws is Noneand swallows exceptions, so it is a no-op on the async (no---wait) path whereconnect()never ran, and idempotent with the SIGINT-token close (which is left untouched — it's what breaks the blockingrecv()on Ctrl-C).--print-prompt) occur beforeexecutionis constructed and before any ws is opened, so there is nothing to leak there.Tests
test_successful_executionnow assertsmock_exec.ws.close.assert_called_once()after a successful--waitrun.test_websocket_closed_on_watch_failureassertsclose()is also called whenwatch_executionraises (WebSocketTimeoutException).pytest tests/ -k run→ 314 passed, 2 skipped.Verification note
The unit tests assert
close()is invoked on both the success and watch-failure paths (non-vacuous: absent the fix,close()is never called on the success path since the only other wiring is the SIGINTon_cancel, which doesn't fire without a signal). The livelsof/server-log confirmation in the ticket's Verification section requires a running ComfyUI server and was not run in this unattended environment.