fix(desktop): guard terminal resume against in-flight connect

Merged
SA
5mo ago
+5-3

Follow-up to #5135, addressing the race flagged by Greptile (P1) and cubic (P2) in review.

Problem

handleResume only bailed when transport.socket was OPEN/CONNECTING. But for remote /hosts/ URLs, connect() runs primeRelayAffinity asynchronously before opening the socket, so there's a window where transport.socket is null while connectionState is "connecting".

Wake-time sequence that orphans a socket:

  1. watchdog fires → reconnectNow → connect() starts the async pre-flight → transport.socket is null, state "connecting"
  2. an online/focus/visibilitychange event fires → handleResume sees the null socket, skips the early-return, calls reconnectNow again
  3. both pre-flights resolve and each calls openSocket() (both pass the currentUrl/connectionState guards), opening two WebSockets — the first is overwritten in transport.socket without being closed, leaving it orphaned on client and server.

Fix

Bail out of handleResume when connectionState === "connecting" too, covering the pre-flight window. reconnectNow is deliberately left unguarded so the watchdog can still force-recycle a genuinely half-open socket (which reports "open") or a hung connect.

Testing

bun test (3 pass), bun run lint (clean), bun run typecheck (pass).


Open in Stage

Summary by cubic

Prevent double WebSocket openings during terminal resume by bailing out when a connect is already in flight. This avoids orphaned sockets on remote /hosts/ connections.

  • Bug Fixes
    • In handleResume, return early when connectionState === "connecting" or the socket is OPEN, covering the pre-flight window before transport.socket is set.

Summary by CodeRabbit

  • Bug Fixes
    • Improved terminal connection handling to prevent duplicate reconnections by better checking the connection state before attempting to reconnect.