import { execFileSync } from "node:child_process"; import { createHash } from "node:crypto"; import fsSync from "node:fs"; import fs from "node:fs/promises"; import net from "node:net"; import path from "node:path"; import { z } from "zod"; import { resolveConfigPath, resolveGatewayLockDir, resolveStateDir } from "../config/paths.js"; import { isPidAlive } from "../shared/pid-alive.js"; import { safeParseJsonWithSchema } from "../utils/zod-parse.js"; import { isGatewayArgv, parseProcCmdline, parseWindowsCmdline } from "./gateway-process-argv.js";
// On Linux, an extra start-time comparison catches PID recycling even when // the replacement process also looks like a gateway (same argv shape). if (platform === "linux") { const payloadStartTime = payload?.startTime; if (Number.isFinite(payloadStartTime)) { const currentStartTime = readLinuxStartTime(pid); if (currentStartTime == null) { return"unknown";
} return currentStartTime === payloadStartTime ? "alive" : "dead";
}
}
const readFn = readCmdline ?? ((p: number) => defaultReadProcessCmdline(p, platform)); const args = readFn(pid); if (!args) { // Cmdline reader unavailable or failed. On Linux legacy locks (no // start-time), "unknown" lets the stale-lock heuristic eventually reclaim // very old locks. On win32/darwin/other, conservatively assume "alive" to // preserve single-instance guarantees when wmic/ps is unavailable. return platform === "linux" ? "unknown" : "alive";
} return isGatewayArgv(args) ? "alive" : "dead";
}
lastPayload = await readLockPayload(lockPath); const ownerPid = lastPayload?.pid; const ownerStatus = ownerPid
? await resolveGatewayOwnerStatus(
ownerPid,
lastPayload,
platform,
port,
opts.readProcessCmdline,
)
: "unknown"; if (ownerStatus === "dead" && ownerPid) {
await fs.rm(lockPath, { force: true }); continue;
} if (ownerStatus !== "alive") {
let stale = false; if (lastPayload?.createdAt) { const createdAt = Date.parse(lastPayload.createdAt);
stale = Number.isFinite(createdAt) ? now() - createdAt > staleMs : false;
} if (!stale) { try { const st = await fs.stat(lockPath);
stale = now() - st.mtimeMs > staleMs;
} catch { // On Windows or locked filesystems we may be unable to stat the // lock file even though the existing gateway is still healthy. // Treat the lock as non-stale so we keep waiting instead of // forcefully removing another gateway's lock.
stale = false;
}
} if (stale) {
await fs.rm(lockPath, { force: true }); continue;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.