Files
Colby Mchenry 3be906fcf4 test: stop index-daemon-rebuild leaving a suspended daemon on Windows (#2629)
A full suite run on Windows left a `serve --mcp --path %TEMP%\cg-rebuild-…`
process behind. Its parent was gone, and its one thread was suspended with
0 CPU used. It would never exit, and it held the checkout's dist.

libuv creates every detached child suspended on Windows and resumes it only
at the end of `uv_spawn`. A launcher killed inside that call never resumes
its daemon. The daemon never runs, so it writes no daemon.pid, and nothing
can find or stop it.

The rebuild test's teardown killed its launcher at once. The test stops the
daemon on purpose, so by then the launcher is serving calls in-process with
a retry timer running. When the retry comes due during the last call, the
launcher spawns its daemon as soon as that call answers, just as the
teardown begins. Under load the two coincide.

The teardown now:
- closes each launcher's stdin and waits for it to exit. A graceful exit
  can't land inside the synchronous spawn.
- records the daemons each launcher spawns (#1773's recorder) and stops them
  until all have exited. One spawned as its launcher exited may still be
  starting, and stopDaemonAt leaves a daemon running until it answers.

The recorder's comment now says that a launcher killed mid-spawn records
nothing.

CODEGRAPH_DAEMON_RETRY_MS=2500 puts the retry inside the last call on a
quiet box. Under it, main's test left a daemon in 6 of 12 runs: 2 suspended
ones, plus 4 live ones whose fixture then failed to delete. This test left
nothing in 12 runs. Of the mutants, killing launchers again, a single
stopDaemonAt and no spawn recorder each leaked. The other daemon test files
left nothing in 2 runs each.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:14:14 +00:00
..