Repository navigation
fix(launcher): fail fast when the spawned proxy child exits pre-bind - #481
Conversation
Salvages the one non-duplicated improvement from superseded PR #480 (its handshake-file TOCTOU fix and --debug removal are already in master via #417 instance governance). ensureProxyRunning now watches the spawned child's exit event and breaks the health-poll loop early, so a startup crash reports in ms instead of burning the full SPAWN_WAIT_MS (20s) window. Error carries the exit code/signal and points at the per-launch log.
📦 Built Package ArtifactBranch: Option A — Install from npm PR tag (recommended)npm install -g billion-context@pr-481Each push to this PR publishes a new version under the Option B — Download artifact
tar xzf billion-context-pr481.tgz
npm install -g packageThis comment is automatically updated on each push. |
[bot] 🏷 Picked up. Verified the premise on master: |
[bot] 🏷 Done — PR: #482 What changed (branch
Verification (matches your stated bar):
Success path untouched: a live child never emits |
[bot] 🏷 Cross-reference: a second, independent implementation of this same fix landed as PR #482 (branch Per duplicate screening I closed #482 as |
|
Review vs master 3cd85b6: ✅ merge-ready.
One nit (non-blocking): the fast-fail error could also mention the child command ( (tracking: #596) |
Closes #596 — tracking issue for this PR.
Context
Salvages the one non-duplicated improvement from PR #480 ("child-reported handshake bind; stop forcing --debug").
While reviewing #480 I found that two of its three goals are already merged into master via an independent, more complete implementation — commit
c2567cc"instance governance … (#417)":EADDRINUSE(≤17 attempts), reporting its real origin through the instance file matched byBILI_LAUNCH_TOKEN(src/server.ts, andensureProxyRunninginsrc/launcher.ts).debug: trueis already removed (proxyStartArgsusesopts.debug).Merging #480 as-is would add a second, competing handshake mechanism (a per-launch
--handshake-file) and conflicts with master insrc/launcher.ts,src/server.ts, andtests/launcher.test.ts(all changed-in-both since #480's base). So #480 should be closed as superseded by #417.The single piece of #480 that master still lacks is fast-fail on child exit: if the spawned proxy dies before becoming healthy (bad config, missing upstream, startup crash), master's spawn path waits the full
SPAWN_WAIT_MS = 20000before erroring — there is nochild.on("exit")watch insideensureProxyRunning(the only exit handler lives inrunClient).Change
src/launcher.tsensureProxyRunning: register anexitlistener on the spawned child; break the health-poll loop as soon as it fires; throw a specific error carrying the exit code/signal and pointing at the per-launch log instead of the generic 20s timeout message.tests/launcher.test.ts: new test — the child firesexit(1)right after spawn →ensureProxyRunningrejects in well under 5s withexited before becoming healthy (code 1)plus the log path.The success path is untouched: a live child never emits
exitduring polling, so normal startup behavior is unchanged.Verification
npm run typecheck— cleannpm test— 947/948 pass; the single failure (resolveClientCommand: codex/claude resolve to themselves) is the pre-existing env-dependent one (this sandbox has/usr/bin/codex), reproduces identically on pristine master, unrelated to this changenpm run build— cleanPartially supersedes #480; see that thread for the full duplicate analysis.