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

Function tryAcquireDaemonLock

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

Source from the content-addressed store, hash-verified

553 * drive that's strictly better than the daemon never starting at all.
554 */
555export function tryAcquireDaemonLock(projectRoot: string): AcquireResult {
556 const pidPath = getDaemonPidPath(projectRoot);
557 // Make sure the .codegraph/ directory exists — the daemon may be the first
558 // thing to touch it on a fresh-clone-but-already-initialized checkout.
559 fs.mkdirSync(path.dirname(pidPath), { recursive: true });
560
561 const info: DaemonLockInfo = {
562 pid: process.pid,
563 version: CodeGraphPackageVersion,
564 socketPath: getDaemonSocketPath(projectRoot),
565 startedAt: Date.now(),
566 };
567
568 // Temp name is pid-scoped so racing candidates never collide on it.
569 const tmp = `${pidPath}.${process.pid}.tmp`;
570 let acquired = false;
571 try {
572 fs.writeFileSync(tmp, encodeLockInfo(info), { mode: 0o600 });
573 try {
574 fs.linkSync(tmp, pidPath); // atomic + exclusive (race-free; see must-fix 1)
575 acquired = true;
576 } catch (err: unknown) {
577 if ((err as NodeJS.ErrnoException).code === 'EEXIST') {
578 // Lost the race — another candidate already holds it. Fall through to read.
579 } else {
580 // link() failed for a non-conflict reason — nearly always "this filesystem
581 // has no hard links" (ExFAT/FAT external volumes, some network mounts),
582 // which surfaces as a DIFFERENT errno on every OS: ENOTSUP on macOS, EPERM
583 // on Linux, EISDIR on Windows (#997). Enumerating them is whack-a-mole and
584 // unnecessary: the `tmp` write above already proved this directory is
585 // writable, so an O_EXCL create is a valid atomic+exclusive substitute. If
586 // IT fails too, that's a genuine error and propagates. EEXIST ⇒ taken.
587 acquired = acquireLockViaExclusiveOpen(pidPath, info);
588 }
589 }
590 } finally {
591 try { fs.unlinkSync(tmp); } catch { /* temp already gone */ }
592 }
593
594 if (acquired) return { kind: 'acquired', pidPath, info };
595
596 // Taken. Because the pidfile was link'd atomically it always holds a complete
597 // record — `existing` is null only for a genuinely corrupt leftover, never a
598 // mid-write race.
599 let existing: DaemonLockInfo | null = null;
600 try {
601 existing = decodeLockInfo(fs.readFileSync(pidPath, 'utf8'));
602 } catch { /* unreadable lockfile — treat as malformed */ }
603 return { kind: 'taken', existing, pidPath };
604}
605
606/**
607 * 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