Skip to content

fix(windows): replace cmd handoff with Node.js subprocess for gateway restart#92726

Closed
likuoping136 wants to merge 1 commit into
openclaw:mainfrom
likuoping136:fix/windows-restart-handoff
Closed

fix(windows): replace cmd handoff with Node.js subprocess for gateway restart#92726
likuoping136 wants to merge 1 commit into
openclaw:mainfrom
likuoping136:fix/windows-restart-handoff

Conversation

@likuoping136

@likuoping136 likuoping136 commented Jun 13, 2026

Copy link
Copy Markdown

Problem

On Windows, the /restart command (and config-change triggered restarts) frequently fail to relaunch the gateway. The gateway shuts down but never comes back, requiring manual openclaw gateway restart.

Root Cause

Commit 6d26609 (#52487) added a "Running" state check to the cmd.exe handoff script to avoid duplicate schtasks /Run calls. However, this introduces a race condition:

  1. /restart fires → gateway process exits
  2. Handoff script spawns and checks Get-ScheduledTask.State
  3. Windows Task Scheduler still reports "Running" due to delayed state updates after process exit
  4. Handoff script sees "Running" → assumes another path already restarted → jumps to cleanup
  5. No new instance is launched — gateway stays offline

The cmd script also spawns powershell.exe | findstr.exe, which creates visible console popup windows even with windowsHide: true, because the piped child processes aren't hidden.

Fix

Replace the cmd.exe handoff script with a detached Node.js subprocess that:

  1. Writes a temporary .mjs restart launcher
  2. schtasks /End — signals the Task Scheduler to stop the old task
  3. The launcher polls schtasks /Query until the task is confirmed NOT running
  4. Force-kills the process on port 18789 if the task won't stop (timeout fallback)
  5. schtasks /Run — starts the new instance once the old one is confirmed gone
  6. Falls back to launching gateway.cmd directly if schtasks /Run fails

Why Node.js instead of cmd script?

  • No console popupswindowsHide: true works correctly on Node.js child processes
  • No race condition — explicitly waits for task to stop before launching new instance
  • Better logging — structured log lines with timestamps
  • Force-kill fallback — handles stuck processes that refuse to die

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: Windows /restart should relaunch the managed OpenClaw Gateway Scheduled Task without leaving the gateway offline and without visible cmd / findstr console popups.

  • Real environment tested: Real Windows 10 machine (Build 19045), OpenClaw 2026.6.6, managed Windows Scheduled Task named OpenClaw Gateway, WebChat /restart command.

  • Exact steps or command run after this patch:

    1. Reproduced the issue with the published Windows task handoff implementation.
    2. Observed /restart shut down the gateway and leave it offline until manual openclaw gateway restart.
    3. Patched the local installed OpenClaw restart handoff to use the Node subprocess strategy from this PR.
    4. Restarted the gateway so the patched code was loaded.
    5. Ran /restart twice from WebChat.
    6. Observed the gateway relaunch both times with no black console windows.
  • Evidence after fix (screenshot, recording, terminal capture, console output, redacted runtime log, linked artifact, or copied live output):

    2026/6/13 23:06:25 openclaw restart attempt source=node-handoff target=OpenClaw Gateway
    2026/6/13 23:06:25 launching task via schtasks /Run
    2026/6/13 23:06:25 schtasks /Run exit=0 out=成功: 尝试运行计划任务 "OpenClaw Gateway"�?  2026/6/13 23:06:25 openclaw restart finished source=node-handoff
    2026/6/13 23:08:21 openclaw restart attempt source=node-handoff target=OpenClaw Gateway
    2026/6/13 23:08:21 launching task via schtasks /Run
    2026/6/13 23:08:21 schtasks /Run exit=0 out=成功: 尝试运行计划任务 "OpenClaw Gateway"�?  2026/6/13 23:08:21 openclaw restart finished source=node-handoff
    
  • Observed result after fix: /restart completed successfully on both attempts, the gateway came back immediately, and no visible findstr / cmd console windows appeared.

  • What was not tested: Windows 11 and non-default gateway ports.

  • Proof limitations or environment constraints: The proof used copied redacted runtime logs instead of screenshots/recordings. The task name tested was the default OpenClaw Gateway; custom task names are covered by unit tests but not by the live Windows proof.

  • Before evidence (optional but encouraged):

    [周六 2026/06/13 22:30:07.92] openclaw restart log initialized
    [周六 2026/06/13 22:30:07.92] openclaw restart attempt source=windows-task-handoff target="OpenClaw Gateway"
    [周六 2026/06/13 22:31:11.95] openclaw restart finished source=windows-task-handoff
    [周六 2026/06/13 22:40:37.72] openclaw restart log initialized
    [周六 2026/06/13 22:40:37.72] openclaw restart attempt source=windows-task-handoff target="OpenClaw Gateway"
    [周六 2026/06/13 22:41:35.34] openclaw restart finished source=windows-task-handoff
    

    Those 60s+ gaps corresponded to the old handoff path; the gateway did not reliably relaunch and the user had to manually recover it. During this path, visible black console windows appeared with findstr involved.

Tests and validation

Which commands did you run?

  • GitHub CI for the latest pushed commit: check-prod-types, check-test-types, check-lint, and the affected infra test shard passed.
  • Live Windows /restart command was run twice from WebChat after applying the local patch.

What regression coverage was added or updated?

  • Updated src/infra/windows-task-restart.test.ts to cover the Node handoff launcher, custom task names, fallback content, and windowsHide: true.

@openclaw-barnacle openclaw-barnacle Bot added size: M triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 13, 2026
@clawsweeper

clawsweeper Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Keep this PR open: it targets a real Windows gateway restart availability problem, but the current patch is not merge-ready because it bypasses existing quoting, configured-port, PID-verification, locale-independent status, and helper-cleanup contracts, and the supplied proof is still too thin for the Windows user path.

Canonical path: Close this PR as superseded by #52487.

So I’m closing this here and keeping the remaining discussion on #52487.

Review details

Best possible solution:

Close this PR as superseded by #52487.

Do we have a high-confidence way to reproduce the issue?

Yes for the PR-introduced defects: source inspection shows raw cmd task-name interpolation, hard-coded port killing, localized task-state parsing, and missing helper cleanup. I did not live-reproduce the original Windows scheduler race in this read-only review.

Is this the best way to solve the issue?

No: the proposed rewrite is plausible but bypasses existing safety contracts in the scheduled-task owner path. The safer solution is to keep the restart handoff repair inside those established quoting, port, PID-verification, and cleanup contracts.

Security review:

Security review needs attention: Needs attention: the diff introduces raw cmd command-string parsing and an unverified taskkill fallback in a Windows restart path.

  • [medium] Raw task name passed through cmd.exe — src/infra/windows-task-restart.ts:136
    The Scheduled Task name is interpolated into a cmd.exe /c string for schtasks /End, so custom task names or profiles with cmd metacharacters can alter command parsing.
    Confidence: 0.9
  • [medium] Unverified taskkill fallback — src/infra/windows-task-restart.ts:83
    The Node launcher finds a PID by matching :18789 in netstat output and runs taskkill /F without resolving the configured gateway port or verifying that the PID belongs to OpenClaw.
    Confidence: 0.92

AGENTS.md: found and applied where relevant.

What I checked:

  • linked superseding PR: fix(windows): prevent restart race from duplicate schtasks /Run #52487 (fix(windows): prevent restart race from duplicate schtasks /Run) is merged at 2026-05-11T10:32:49Z.
  • cluster evidence: the durable review links that PR in the work cluster or recommended risk path.
  • no human follow-up: live comments and timeline hydrated by apply contain no non-automation activity after the ClawSweeper review.

Likely related people:

  • andyk-ms: Authored the merged Windows restart guard in fix(windows): prevent restart race from duplicate schtasks /Run #52487 that added the PowerShell running-state check this PR replaces. (role: introduced behavior; confidence: high; commits: 6d26609f7baf; files: src/infra/windows-task-restart.ts, src/infra/windows-task-restart.test.ts)
  • BradGroux: Merged the prior Windows restart guard PR and is also carrying the open Microsoft/Windows tracker that cross-references this PR. (role: merger; confidence: medium; commits: 6d26609f7baf; files: src/infra/windows-task-restart.ts, src/infra/windows-task-restart.test.ts)
  • imechZhangLY: Authored the adjacent Windows restart fallback work in the same helper for unregistered scheduled tasks. (role: adjacent contributor; confidence: medium; commits: 0e61a1d0caf4; files: src/infra/windows-task-restart.ts, src/infra/windows-task-restart.test.ts)
  • arifahmedjoy: Authored the Windows self-restart stale gateway cleanup and Windows port PID helper work that is directly relevant to the PR's taskkill fallback. (role: adjacent process-safety contributor; confidence: medium; commits: 63fcc52520d6; files: src/infra/gateway-processes.ts, src/infra/restart-stale-pids.ts, src/infra/windows-port-pids.ts)

Codex review notes: model internal, reasoning high; reviewed against b3968f69c910.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jun 13, 2026
@likuoping136
likuoping136 force-pushed the fix/windows-restart-handoff branch 2 times, most recently from d923027 to 4d5668a Compare June 13, 2026 16:05
… restart

The existing cmd.exe handoff script has two critical bugs on Windows:

1. Race condition: After /restart, the old gateway exits but the Windows
   Task Scheduler still reports the task as Running due to delayed state
   updates. The handoff script checks for Running and skips schtasks /Run,
   incorrectly assuming another restart path already started a new instance.
   This leaves the gateway offline until manual intervention.

   Root cause: commit 6d26609 (openclaw#52487) added a PowerShell+findstr check
   for Running state before retrying schtasks /Run. The intent was to
   avoid duplicate /Run calls, but the check treats the stale Running
   state from the dying old process as evidence of a successful restart.

2. Visible console windows: The cmd script spawns powershell.exe piped to
   findstr.exe, which creates visible console popups even with windowsHide.
   This is confusing and disruptive to users.

Fix: Replace the entire cmd.exe handoff script with a detached Node.js
subprocess that:
- First signals schtasks /End to stop the old task
- Polls until the task is confirmed not running (with timeout + force-kill)
- Then runs schtasks /Run to start the new instance
- Falls back to gateway.cmd if schtasks /Run fails
- Uses windowsHide on all child processes (no visible windows)

Tested on Windows 10 with /restart command: gateway restarts reliably
in under 1 second with no visible console windows.
@likuoping136
likuoping136 force-pushed the fix/windows-restart-handoff branch from 4d5668a to 9e19a5f Compare June 13, 2026 16:11
@clawsweeper clawsweeper Bot added status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 13, 2026
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 13, 2026
@clawsweeper clawsweeper Bot added status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. labels Jun 13, 2026
@clawsweeper

clawsweeper Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper applied the proposed close for this PR.

  • Action: closed this PR.
  • Close reason: duplicate or superseded.
  • Evidence: durable ClawSweeper review.
  • Coverage proof: PR B carries the concrete Windows scheduled-task restart fix path that PR A is trying to replace, and it directly preserves or fixes the key safety/proof concerns raised against PR A. PR A's remaining details are implementation-specific defects in its superseded Node rewrite, not independent useful work that still needs separate review. Covering PR: fix(windows): prevent restart race from duplicate schtasks /Run #52487.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P1 High-priority user-facing bug, regression, or broken workflow. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: M status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant