/** * Process start-token probe: the "is this still the same process?" half of pid * identity. * * A pid alone does not identify a process. Operating systems hand numbers back * out, and faster than intuition suggests: one development machine runs a * `pid_max` of 99999 against roughly 100 new processes a second, turning the * whole space over about every quarter hour. Anything that remembers a pid for * longer than that is remembering a number, not a process. * * A start token pins the pair down. Two processes can share a pid but never a * pid *and* a start instant, so a recorded `(pid, token)` either still names the * process that was recorded or plainly does not. * * The token is opaque on purpose. Callers compare it for equality and nothing * else, which is why no clock arithmetic appears here: Linux reports ticks since * boot and BSD reports a formatted date, and neither needs converting to be * compared with itself. A platform that will not answer returns null, meaning * "unverifiable" — callers fall back to a plain liveness check, which is where * they were before this existed. * * Two rules keep comparison honest, and both exist because getting them wrong * reports a *false* mismatch, which prunes a live row and hands the identity * walk the same wrong answer this module was written to stop: * * 1. One machine uses one probe. The probe is chosen by capability and locked * in, never fallen back from, so a transient read failure cannot answer in * the other probe's dialect and read as a recycled pid. * 2. A probe's output must not depend on who asked. The `ps` text is formatted * through the caller's locale and timezone, so both are pinned; without that, * two callers reading the same live process disagree. */ /** Which probe answers "when did this process start?" on this machine. */ export type StartTokenProbe = "procfs" | "ps"; /** * Which probe this machine uses, decided once. * * `HARNERY_PID_PROBE` forces the choice. That exists so the `ps` path can be * exercised on a procfs machine — it is the same code on either OS, and running * it only on hardware we happen to own is how a branch rots. */ export declare function startTokenProbe(): StartTokenProbe; /** Forget the cached probe and boot id. Tests only. */ export declare function resetStartTokenCaches(): void; /** * `l[.]` from `/proc//stat`, with no subprocess. * * The tick count is field 22, counted from the end of the comm field rather * than by splitting the whole line, because comm is the executable name in * parentheses and may itself contain spaces and parens. The boot segment is * dropped rather than faked when the kernel will not name its boot, which * yields the pre-boot-id shape that `tokensAgree` still accepts. */ export declare function procfsStartToken(pid: number): string | null; /** * `p` from one `ps -o lstart=`, for machines without procfs. * * Second resolution is ample: telling two runs of one pid apart would need the * entire pid space to recycle inside a second. The runner is injectable so the * parsing and the env pinning can be tested without a process to look at. */ export declare function psStartToken(pid: number, run?: (pid: number) => { status: number | null; stdout: string; }): string | null; /** * An opaque token identifying *this run* of `pid`, or null when the platform * will not say. */ export declare function processStartToken(pid: number): string | null; /** * Do two tokens describe the same run? * * Equality, plus one concession: a row written before tokens carried a boot * segment recorded the tick count alone, so it is compared on the part it * actually recorded. Refusing that would call every pre-upgrade row a recycled * pid and prune a working machine's live rows the first time the new code ran. * Such a row loses its reboot protection until the next write rewrites it, * which is a strictly better position than the one it came from. */ export declare function tokensAgree(recorded: string, current: string): boolean; /** * Does `pid` still name the process a row recorded? * * Three answers, and the difference between the last two matters: * * - `"match"` — recorded token, current token, same run. The row is trustworthy. * - `"mismatch"` — both present and different. The pid was recycled. This is * the case a liveness check cannot see, because a recycled pid is alive. * - `"unverified"` — no recorded token (a row written before tokens existed) or * no current one (an unsupported platform). Callers treat this the way they * treated every row previously: trust it if the pid is alive. */ export declare function checkPidToken(pid: number, recorded: string | undefined): "match" | "mismatch" | "unverified"; //# sourceMappingURL=proc-start.d.ts.map