Skip to content

fix(runtime): prevent orphaned copilot processes on shutdown#223

Merged
jafreck merged 1 commit intomainfrom
fix/orphan-process-cleanup
Mar 27, 2026
Merged

fix(runtime): prevent orphaned copilot processes on shutdown#223
jafreck merged 1 commit intomainfrom
fix/orphan-process-cleanup

Conversation

@jafreck
Copy link
Copy Markdown
Owner

@jafreck jafreck commented Mar 27, 2026

Problem

When the AAMF runtime is terminated (e.g. terminal killed, SIGHUP), copilot CLI agent processes are left running as orphans. In one observed case, 55 copilot processes survived after killing the migration terminal.

Root cause (two issues):

  1. Copilot children not tracked for cleanup. spawnAgent() in agent-launcher.ts spawns copilot CLI processes with { detached: true } and child.unref(), making them independent of the parent Node process. However, these children were not registered with the framework's trackProcess() mechanism. The shutdown handler calls killAllActiveProcesses(), but that only kills tracked processes — the copilot agents were invisible to it.

  2. No SIGHUP handler. The runtime handles SIGINT and SIGTERM but not SIGHUP. When a terminal is closed/killed, the OS sends SIGHUP. Without a handler, the Node process dies without running cleanup, and detached children survive unconditionally.

Fix

  • Track copilot children: Call trackProcess(child) immediately after spawn in spawnAgent() so copilot CLI processes are registered with the framework process tracker and cleaned up by killAllActiveProcesses() on shutdown.
  • Handle SIGHUP: Add process.on('SIGHUP', ...) in setupShutdownHandlers() alongside SIGINT/SIGTERM so terminal-close scenarios trigger the same graceful shutdown path.

Changes

File Change
src/core/agent-launcher.ts Import trackProcess, call it after copilot child spawn
src/core/runtime.ts Add SIGHUP handler in setupShutdownHandlers()
tests/core/runtime.test.ts Update shutdown test to verify SIGHUP registration

Testing

  • All 1498 unit tests pass
  • tsc --noEmit clean

spawnAgent() in agent-launcher creates detached+unref child processes
for copilot CLI invocations but did not register them with the framework
process tracker. When the runtime shut down (or the terminal was killed),
killAllActiveProcesses() could not reach these children, leaving them
running indefinitely.

- Call trackProcess(child) after spawn in spawnAgent() so copilot
  children are cleaned up by killAllActiveProcesses() on shutdown
- Add SIGHUP handler alongside SIGINT/SIGTERM in setupShutdownHandlers()
  so terminal-close scenarios trigger the same cleanup path
- Update shutdown handler test to verify SIGHUP registration
@jafreck jafreck merged commit 4e91e53 into main Mar 27, 2026
1 check passed
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