Commit Graph
4 Commits
Author SHA1 Message Date
Shane McCarronandClaude Opus 5 3cf2a6663f fix(daemon): address QA round 1
- Separate loss from transient failure. Touch helpers now report OK /
  lost / transient (version_cohort: OK/UNSAFE/IO; ipc: 1/0/-1). Only a
  proven unlink or replacement stops the daemon. A refresh failure on a
  still-valid file (EROFS, EPERM, EMFILE on the marker reopen) logs
  daemon.coordination_touch_failed once, retries every tick, and logs
  daemon.coordination_touch_recovered when it clears.
- Cohort and claim locks now prove the path still names the held inode
  (private_file_revalidate against the stored directory + name), not
  just st_nlink, so rename-away, hard-link+unlink and a replaced
  directory are caught like unlink.
- The runtime service's self-owned participant guard is refreshed by
  the listener heartbeat too.
- Tests: rename-away detection; cohort lease/claim touch (lease with
  only lifetime held is OK, each unlinked file reported independently);
  IPC listener touch now checks timestamps are actually refreshed and
  covers the participant guard and identity-marker replacement.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>
2026-09-21 13:02:07 -05:00
Shane McCarronandClaude Opus 5 9e793df87b fix(daemon): keep held runtime files fresh and exit when one is lost
macOS com.apple.tmp_cleaner deletes /tmp files whose atime, mtime and
ctime are all older than three days. The daemon's long-held lock files
are empty and never written, so under a daemon that lives past three
days the cleaner unlinks them while they are held. The next participant
then creates and locks a fresh inode: forked index workers see the
cohort daemon marker as free, read the live daemon as uncoordinated and
exit 1 on every reindex, and a lost IPC lifetime lock or cohort lifetime
file stops protecting the generation at all. A lost socket identity
marker additionally makes listener close leave the socket pair behind.

The host lifetime loop now runs a heartbeat every 60 s over every file
the generation holds (cohort daemon claim and lease, participant guard,
IPC lifetime reservation, identity marker). Each file is refreshed with
futimens through its held descriptor, only after proving the path still
names that descriptor, so the cleaner never selects it. If any file is
already lost, the daemon logs daemon.lifetime_end
reason=coordination_file_lost and stops cleanly; the next client starts
a coordinated generation. Re-claiming in place would race that client.

Windows needs no refresh (no age-based cleaner; held lock handles deny
deletion), so its entry points only validate the handles.

Closes #2178

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>
2026-09-21 11:48:06 -05:00
Martin Vogel 83c137d2a5 feat: complete shared daemon lifecycle
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-18 01:26:08 +02:00
Martin Vogel 0e00ef5702 feat: coordinate concurrent CBM sessions
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-16 19:20:46 +02:00