mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-18 05:41:18 +08:00
3be906fcf4
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>