Skip to content

fix(hub): kill the whole child-process tree on Windows - #404

Closed
zahidzorbaz wants to merge 1 commit into
devframes:mainfrom
zahidzorbaz:fix/hub-kill-child-process-tree-windows
Closed

zahidzorbaz wants to merge 1 commit into
devframes:mainfrom
zahidzorbaz:fix/hub-kill-child-process-tree-windows

Conversation

@zahidzorbaz

Copy link
Copy Markdown
Contributor

Description

On Windows, stopping a startChildProcess() session left the real program running. tinyexec runs anything that isn't a .exe/.com (including the node_modules/.bin/*.cmd shims) through cmd.exe /d /s /c, so the pid the host holds is the wrapper's. cp.kill() ends only that process, and Windows doesn't kill descendants, so e.g. vitest --ui kept running and kept its port.

This PR:

  • adds killProcessTree() in host-terminals.ts: on Windows, while the run is alive, it runs taskkill /pid <pid> /T /F and falls back to cp.kill() if taskkill fails; elsewhere it is cp.kill() as before.
  • uses it in terminate(), restart() and the stream's cancel(). restart() now waits for the old tree to exit before spawning the next run, so the new run can take the same ports.
  • keeps host-initiated stops reported the same way on every platform: taskkill /F ends the process with exit code 1 instead of a signal, so runs killed by the host are tracked and report status: 'stopped', exitCode: undefined and killed: true, as they already did on POSIX. The DevframeChildProcessOutput doc comment is updated to match.

POSIX behaviour is unchanged. The PTY path (startPtySession) and @devframes/plugin-terminals are not touched.

Linked Issues

Fixes #402

Additional context

  • Tests: a new describe.runIf(process.platform === 'win32') block in host-terminals.test.ts starts a real .cmd shim that launches node, and checks that terminate(), restart() and stream cancel (via host.remove()) kill the node grandchild, and that terminate() reports stopped/killed with an undefined exit code. All 4 tests fail on main and pass with this change on Windows 11. They are skipped on Linux/macOS CI, since the cmd.exe wrapping only happens on Windows.
  • Gates on Windows 11 / Node 24.21: pnpm lint, pnpm knip and pnpm typecheck pass. pnpm test passes except tests/exports.test.ts > devframe > dts: ./internal, a snapshot export-order mismatch (importAgenticMcp) that also fails on a clean main here and is unrelated to this change.

🤖 Generated with Claude Code

On Windows, tinyexec runs `.cmd` shims (e.g. `node_modules/.bin/vitest.cmd`)
through `cmd.exe`, so `terminate()`, `restart()` and stream cancel only killed
the wrapper and left the real program running and holding its ports. Kill
the tree with `taskkill /T /F` there, wait for it before `restart()` spawns
the next run, and keep reporting host-initiated kills as `stopped` with an
`undefined` exit code on every platform.

Fixes devframes#402

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@coldtea-pr-lens

coldtea-pr-lens Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

◈ PR Lens

🟢 +0 new · 🟠 ~1 changed · 🔴 -0 removed · 1 flow · 2 files · commit 8e4d272


Architecture

Architecture diagram for devframes/devframe at 8e4d272

1 component touched across 2 lanes.

Play the interactive walkthrough


Data flow

Data flow diagram for devframes/devframe at 8e4d272

Terminating Windows child process session

Follow each request, response and payload


View

  • Architecture lens
  • Data flow lens
  • Expand every detail

Tip

Push a commit and the comment redraws for the new head. A slow older run never overwrites a newer one

🪧 More tips
  • Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists
  • Untick Architecture lens or Data flow lens under View to hide a diagram, or tick Expand every detail to open every section. The comment redraws in a few seconds
  • Click the link under each diagram to open it on a canvas you can zoom, pan and step through
  • The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change
  • Open a diagram on the canvas, then press W or click play to walk through the change one step at a time
  • The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time
  • Set github.comment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture and data flow row. Drawing still runs on every push
  • Set github.draw: on-demand in .github/pr-lens.yml and PR Lens stops drawing every push. Comment @pr-lens draw on a pull request when you want that one drawn
  • Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works
  • Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion

Thanks for using PR Lens! It's built by Coldtea, free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

@vercel

vercel Bot commented Sep 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
devframe Skipped Skipped Sep 24, 2026 9:28am UTC

This branch was previously deployed

1 inactive deployment
Preview — 8e4d2727 Deployed Sep 24, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(hub): terminate()/restart() of a startChildProcess session orphans the real process on Windows

2 participants