Skip to content

fix(runner): a run's whole process tree ends with it; Try the app refuses a taken port - #259

Merged
hoangsnowy merged 1 commit into
mainfrom
fix/runner-process-jobs
Oct 22, 2026
Merged

hoangsnowy merged 1 commit into
mainfrom
fix/runner-process-jobs

Conversation

@hoangsnowy

Copy link
Copy Markdown
Owner

Summary

Found on the lab while trying TeacherHub through Try the app:

  • A vite dev server left behind by a finished agent run held port 5173 → the preview said "running" after 5 s (someone else's server).
  • Re-pairing the runner killed only the runner: a whole Claude CLI run (and its dev servers, test host, corpus converter) kept working as an orphan, racing its own restarted task for the same branch.

Fix:

  • ProcessJob — on Windows every CLI run, server-driven shell call and preview runs in a Job Object with KILL_ON_JOB_CLOSE. Background children join automatically; run end / Stop / the runner dying (handle closed by the OS) kills everything left. Non-Windows: kills the current tree.
  • Try the app refuses to start when the recipe's port is already in use ("Something else on this computer is already using port 5173…"), and releases the job when the app ends by itself.

Test plan

  • ProcessJobTests: a detached grandchild that outlived its parent is killed when the job is disposed (Windows); double dispose is harmless.
  • Full suite green locally.
  • Lab: re-pair mid-run → no orphaned claude/vite processes; Try the app with port taken → plain refusal.

🤖 Generated with Claude Code

https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB

…uses a port that's already taken

Found on the lab while trying TeacherHub: a vite dev server left behind by a finished agent run held port 5173, so
Try the app reported "running" within 5 s — a stranger's server. Restarting the runner also left a whole CLI run
working on as an orphan, racing its own retry for the same branch.

- ProcessJob: on Windows each CLI run, server-driven shell call and preview goes into a Job Object with
  KILL_ON_JOB_CLOSE — background children join it, and closing it (run end, Stop, or the runner dying for any
  reason) kills everything left. Elsewhere it kills the current tree.
- PreviewHost: refuses to start when something already listens on the recipe's port, with a plain reason; releases
  the job when the app ends on its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB
@hoangsnowy
hoangsnowy merged commit 3b4a806 into main Oct 22, 2026
4 checks passed
@hoangsnowy
hoangsnowy deleted the fix/runner-process-jobs branch October 23, 2026 00:42
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.

1 participant