v3.16.1 β fix(daemon): close lockfile race window (#2484)
What's fixed in 3.16.1
PATCH bump for issue #2484 β Multiple daemon instances spawned per Claude Code session. EDortta reported 4 identical daemon start --foreground --quiet processes per Claude Code session, accumulating to ~1.7 GB swap on a 16 GB machine with 4 concurrent sessions.
Root cause
TOCTOU window in the launcher's lockfile dedup. The lock was held for the "is a daemon running?" check but released BEFORE startBackgroundDaemon (which forks the real background process and writes the PID file). Concurrent callers could land in the window between lock-release and PID-file-write, see neither lock nor PID, and each fork their own background daemon.
Fix
Hold the lock through the entire spawn lifecycle. The lock-loser now ALWAYS sees either a held lock OR a populated PID file β never the empty window. Three explicit release paths (early-return, background, foreground) so every exit path cleans up.
Verified
- Build clean (
tsc) - 77/77 vitest pass across 3 daemon-related test files
- 6/6 new regression-test cases pass (
daemon-lockfile-race-2484.test.ts) - 101/101 CI checks green on PR #2505 before merge
Install / upgrade
npx ruflo@latest # 3.16.1
npx @claude-flow/cli@latest # 3.16.1
npx claude-flow@latest # 3.16.1npm dist-tags
@claude-flow/cli latest=3.16.1 alpha=3.16.1 v3alpha=3.16.1
claude-flow latest=3.16.1 alpha=3.16.1 v3alpha=3.16.1
ruflo latest=3.16.1 alpha=3.16.1 v3alpha=3.16.1
Related
- PR #2505 β fix(daemon): hold lockfile through spawn lifecycle
- PR #2506 β chore(release): 3.16.0 β 3.16.1
- Issue #2484 β Multiple daemon instances spawned per Claude Code session
- Builds on the lockfile work originally added for #2407 (39 zombie daemons β ~8.5 GiB) β this closes the remaining race window that left the older fix incomplete.