Skip to content

Windows: taskkill without /F leaks npx-spawned child processes (MCP servers, sub-agents) #110789

Description

@AOLIKEJI

Bug Description

On Windows, killProcessTree sends taskkill /T /PID <n> (SIGTERM-equivalent, no /F) as the first attempt, then waits DEFAULT_GRACE_MS (3s) before force-killing with /F.

npx-spawned child processes (MCP servers like @modelcontextprotocol/server-filesystem, sub-agent runners, etc.) do not respond to taskkill without /F. If the gateway restarts within the 3-second grace window (e.g., watchdog auto-restart), the cleanup never reaches the /F path and zombie processes accumulate.

Root Cause

kill-tree-Cr15jS_s.js:

function signalProcessTreeWindows(pid, signal) {
    runTaskkill(signal === "SIGKILL" ? [
        "/F",    // only SIGKILL has /F
        "/T",
        "/PID", String(pid)
    ] : [
        "/T",    // SIGTERM: no /F, npx processes ignore this
        "/PID", String(pid)
    ])
}

Impact

Observed on a Windows 10 machine with 17 agents + MCP servers:

session disconnect
  -> MCP disposeSession() -> taskkill /T (no /F) -> npx child ignores
  -> gateway restarts before 3s grace -> cleanup interrupted
  -> zombie node.exe x 20+ -> 2GB+ memory leak
  -> OOM -> gateway killed -> watchdog restarts -> cycle repeats

This caused daily gateway crashes over a week (July 11-18), each time accumulating more zombies until the system hit memory limits.

Proposed Fix

Option A (recommended): Always force-kill on Windows. npx-spawned processes cannot do graceful shutdown on this platform.

 function signalProcessTreeWindows(pid, signal) {
-    runTaskkill(signal === "SIGKILL" ? [
-        "/F",
-        "/T",
-        "/PID", String(pid)
-    ] : [
-        "/T",
-        "/PID", String(pid)
-    ]);
+    // Windows: always use /F because npx-spawned child
+    // processes don't respond to graceful taskkill.
+    runTaskkill(["/F", "/T", "/PID", String(pid)]);
 }

Option B (more conservative): Increase DEFAULT_GRACE_MS from 3000 to 10000 to give npx processes more time, though this doesn't fix the underlying issue that they don't respond to non-force kill.

Environment

  • OS: Windows 10.0.26200 (x64)
  • Node: 24.16.0
  • OpenClaw: 2026.7.1-2 (0790d9f)

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.impact:crash-loopCrash, hang, restart loop, or process-level availability failure.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions