MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / tryAcquireDaemonLock

Function tryAcquireDaemonLock

src/mcp/daemon.ts:643–694  ·  view source on GitHub ↗
(projectRoot: string)

Source from the content-addressed store, hash-verified

641 * drive that's strictly better than the daemon never starting at all.
642 */
643export function tryAcquireDaemonLock(projectRoot: string): AcquireResult {
644 const pidPath = getDaemonPidPath(projectRoot);
645 // Make sure the .codegraph/ directory exists — the daemon may be the first
646 // thing to touch it on a fresh-clone-but-already-initialized checkout.
647 fs.mkdirSync(path.dirname(pidPath), { recursive: true });
648
649 const info: DaemonLockInfo = {
650 pid: process.pid,
651 version: CodeGraphPackageVersion,
652 socketPath: getDaemonSocketPath(projectRoot),
653 startedAt: Date.now(),
654 };
655
656 // Temp name is pid-scoped so racing candidates never collide on it.
657 const tmp = `${pidPath}.${process.pid}.tmp`;
658 let acquired = false;
659 try {
660 fs.writeFileSync(tmp, encodeLockInfo(info), { mode: 0o600 });
661 try {
662 fs.linkSync(tmp, pidPath); // atomic + exclusive (race-free; see must-fix 1)
663 acquired = true;
664 } catch (err: unknown) {
665 if ((err as NodeJS.ErrnoException).code === 'EEXIST') {
666 // Lost the race — another candidate already holds it. Fall through to read.
667 } else {
668 // link() failed for a non-conflict reason — nearly always "this filesystem
669 // has no hard links" (ExFAT/FAT external volumes, some network mounts),
670 // which surfaces as a DIFFERENT errno on every OS: ENOTSUP on macOS, EPERM
671 // on Linux, EISDIR on Windows (#997). Enumerating them is whack-a-mole and
672 // unnecessary: the `tmp` write above already proved this directory is
673 // writable, so an O_EXCL create is a valid atomic+exclusive substitute. If
674 // IT fails too, that's a genuine error and propagates. EEXIST ⇒ taken.
675 acquired = acquireLockViaExclusiveOpen(pidPath, info);
676 }
677 }
678 } finally {
679 try { fs.unlinkSync(tmp); } catch { /* temp already gone */ }
680 }
681
682 if (acquired) return { kind: 'acquired', pidPath, info };
683
684 // Taken. Because the pidfile was link'd atomically it always holds a complete
685 // record — `existing` is null only for a genuinely corrupt leftover, never a
686 // mid-write race.
687 let existing: DaemonLockInfo | null = null;
688 let lockContents: string | null = null;
689 try {
690 lockContents = fs.readFileSync(pidPath, 'utf8');
691 existing = decodeLockInfo(lockContents);
692 } catch { /* unreadable lockfile — treat as malformed */ }
693 return { kind: 'taken', existing, lockContents, pidPath };
694}
695
696/**
697 * Exclusive-create the pidfile (O_CREAT|O_EXCL via the `wx` flag) and write the

Calls 5

getDaemonPidPathFunction · 0.90
getDaemonSocketPathFunction · 0.90
encodeLockInfoFunction · 0.90
decodeLockInfoFunction · 0.90

Tested by

no test coverage detected