fix(install): trap SIGINT so Ctrl+C exits cleanly during upgrade doctor#76386
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 3, 2026, 5:05 PM ET / 21:05 UTC. Summary PR surface: Source +6, Tests +50, Other +46. Total +102 across 4 files. Reproducibility: yes. Source inspection on current main shows the installer lacks INT/TERM abort handling, loses child signal status in quiet steps, swallows non-interactive doctor failure, and can enable dashboard launch after doctor without a success check. Review metrics: none identified. Stored data model 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:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this focused installer/doctor cancellation fix after normal maintainer review, then close the linked installer Ctrl+C issues with the merge commit. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection on current main shows the installer lacks INT/TERM abort handling, loses child signal status in quiet steps, swallows non-interactive doctor failure, and can enable dashboard launch after doctor without a success check. Is this the best way to solve the issue? Yes. The latest head is the narrowest maintainable fix found because it repairs installer signal/status propagation and dashboard gating while keeping shared non-doctor Clack cancellation behavior unchanged. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 010b61746379. Label changesLabel justifications:
Evidence reviewedPR surface: Source +6, Tests +50, Other +46. Total +102 across 4 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
|
|
This is a bug fix, not a refactor — the Reproduction: Run Root cause: No This PR fixes real user-facing misbehavior — Ctrl+C during the installer should exit the installer, not silently continue and open dead browser tabs. |
|
@fabianwilliams — this fixes a user-facing bug where Ctrl+C during |
26d8b98 to
c5b41aa
Compare
c5b41aa to
1cd353a
Compare
1cd353a to
ce5d7de
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
ClawSweeper PR egg ✨ Hatched: 🥚 common Cosmic Crabkin Hatch commandComment Hatchability rules:
Rarity: 🥚 common. What is this egg doing here?
|
|
@clawsweeper re-review |
|
🦞👀 Command router queued. I will update this comment with the next step. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞👀 Command router queued. I will update this comment with the next step. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
|
🦞👀 Command router queued. I will update this comment with the next step. Re-review progress:
|
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
Three changes to fix the install script's Ctrl+C handling: 1. Add INT/TERM signal traps that clean up temp files and exit with the correct signal exit codes (130 for SIGINT, 143 for SIGTERM). 2. Preserve signal exit codes (>128) through run_quiet_step so the doctor path can distinguish user cancellation from normal errors. Non-signal failures still return 1, preserving existing caller semantics for all other installer steps. 3. Fix guardCancel in onboard-helpers.ts: exit(0) changed to exit(1) so Clack prompt cancellation (Escape/Ctrl+C) is treated as failure, not success. This prevents the installer from continuing with plugin updates after the user explicitly cancelled. Signed-off-by: Sebastien Tardif <[email protected]>
When a user cancels the interactive upgrade-doctor prompt (Clack cancellation exits 1, SIGINT exits 130), clear should_open_dashboard so the installer does not launch a dead dashboard after an incomplete upgrade. Also propagate non-zero exit from run_doctor() so the non-interactive upgrade path correctly skips dashboard launch on failure.
The existing-config path called run_doctor without checking its return value, so a failed or cancelled doctor would still launch the dashboard. Now both run_doctor call sites guard the return value with if-then. Adds focused tests verifying: every run_doctor caller is guarded, dashboard flag is cleared on doctor failure, signal exit codes propagate through run_quiet_step, and SIGINT (exit 130) triggers abort_install_int.
guardCancel now exits with 130 (SIGINT convention) instead of 1. When the user presses Ctrl+C at an interactive doctor prompt, the installer sees doctor_exit=130 and calls abort_install_int, aborting cleanly instead of continuing after exit 1. Signed-off-by: Sebastien Tardif <[email protected]>
Revert guardCancel to exit 0 by default (matching main) and pass exit code 130 only from doctor-prompter where the installer needs to distinguish user cancellation from normal failures. This preserves the existing cancellation behavior for configure, wizard, gateway, and daemon prompts while keeping the SIGINT convention for the installer's doctor subprocess. Signed-off-by: Sebastien Tardif <[email protected]>
Update: narrowed exit 130 + rebased onto mainTwo changes:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
No description provided. |
Fixes #90011
Fixes #82304
Problem
When running
curl -fsSL https://openclaw.ai/install.sh | bash, pressing Ctrl+C duringopenclaw doctorin the upgrade flow does not abort the installer. The SIGINT kills the doctor subprocess but the installer catches it as a regular failure, continues past the prompt, and opens a browser to an unconfigured dashboard URL.Fix
abort_install_int/abort_install_termhandlers clean up temp files, show a warning, and exit 130/143openclaw doctorexit code separately; if 130 (SIGINT), callabort_install_intinstead of treating it as a regular failurerun_quiet_step: the wrapper previously normalized all failures to exit 1, which swallowed SIGINT (130). Now returns signal exit codes (>128) so the doctor exit-130 check fires correctly, while preserving exit 1 for non-signal failures to maintain existing caller semantics across all 66+ installer call sitesshould_open_dashboardso the installer does not launch a dead dashboard after an incomplete upgraderun_doctorwithout checking its return value, so a failed doctor would still setshould_open_dashboard=true. Now guarded withif run_doctor; then should_open_dashboard=true; figuardCancelinonboard-helpers.tscalledruntime.exit(0)when the user cancelled at a Clack prompt (Escape key), making the install script treat cancellation as success. Changed toruntime.exit(1)to match theWizardCancelledErrorpattern used byclack-prompter.tsandonboard-interactive.tsReal behavior proof
Behavior addressed: (1) Pressing Ctrl+C during
openclaw doctorin the upgrade flow does not abort the installer; the installer continues and opens a dead dashboard. (2)guardCancelin onboard-helpers exited with 0/1 instead of 130, so the installer could not distinguish user cancellation from regular failure.Real environment tested: macOS 15.5, Node v26.3.0, OpenClaw built from patched source at
/tmp/wt-76386. Gateway started and doctor command exercised on a real OpenClaw deployment.Exact steps or command run after this patch:
Step 1. Built from branch:
CI=true pnpm install --frozen-lockfile && pnpm buildStep 2. Verified the fix in the compiled production bundle (before vs after).
Step 3. Started the patched gateway and ran
openclaw doctor --non-interactiveto confirm the doctor module works correctly.Step 4. Sent SIGINT to the installer during a real upgrade to verify the abort path.
Step 5. Ran the full install script test suite (49 tests).
Evidence after fix: terminal output from the patched build:
Before (upstream/main):
guardCancelexits with 0, making the installer treat Clack cancellation as success:After (patched):
guardCancelexits with 130 (SIGINT convention), which the installer detects and aborts:Install script
run_doctornow detects exit 130:Doctor runs correctly on the live deployment:
Gateway starts cleanly with the patched module:
SIGINT during install triggers clean abort:
All 49 install script tests pass:
Observed result after fix: The compiled production code at
dist/onboard-helpers-D47vq5rt.js:30callsruntime.exit(130)instead ofruntime.exit(0)when the user cancels at a Clack prompt. The install script at line 2835 detectsdoctor_exit == 130and callsabort_install_int, which exits with 130 and the "Installation interrupted" message. Terminal output confirms: (1) doctor runs correctly on the live deployment, (2) SIGINT during install triggers clean abort with exit 130, (3) the gateway loads the patched module without errors.What was not tested: Live interactive Ctrl+C at a real Clack upgrade-doctor prompt (requires a state where doctor triggers an interactive migration question). The exit code propagation from
guardCancel(130)throughrun_doctortoabort_install_intwas verified via the compiled bundle, install script grep, and the 49-test suite.