openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
96 lines (95 loc) • 3.1 kB
JavaScript
import { n as resolveDiagnosticProcessEnv } from "./process-env-DlZFJzq6.js";
import { n as readWindowsProcessStartTimeSync } from "./windows-process-start-B7L5giUg.js";
import fs from "node:fs";
import childProcess from "node:child_process";
//#region src/shared/pid-alive.ts
const PROCESS_START_TIMEOUT_MS = 1e3;
let selfStartTime = null;
function isValidPid(pid) {
return Number.isInteger(pid) && pid > 0;
}
/**
* Check if a process is a zombie on Linux by reading /proc/<pid>/status.
* Returns false on non-Linux platforms or if the proc file can't be read.
*/
function isZombieProcess(pid) {
if (process.platform !== "linux") return false;
try {
return fs.readFileSync(`/proc/${pid}/status`, "utf8").match(/^State:\s+(\S)/m)?.[1] === "Z";
} catch {
return false;
}
}
/** Returns true only when a positive PID exists and is not a Linux zombie process. */
function isPidAlive(pid) {
if (!isValidPid(pid)) return false;
try {
process.kill(pid, 0);
} catch (err) {
if (err.code !== "EPERM") return false;
}
return !isZombieProcess(pid);
}
/** Returns true only when the PID is invalid, missing, or known to be a Linux zombie. */
function isPidDefinitelyDead(pid) {
if (!isValidPid(pid)) return true;
try {
process.kill(pid, 0);
} catch (err) {
return err.code === "ESRCH";
}
return isZombieProcess(pid);
}
function getDarwinProcessStartTime(pid) {
try {
const startedAt = childProcess.execFileSync("/bin/ps", [
"-o",
"lstart=",
"-p",
String(pid)
], {
encoding: "utf8",
env: {
...resolveDiagnosticProcessEnv(),
LC_ALL: "C",
TZ: "UTC"
},
stdio: [
"ignore",
"pipe",
"ignore"
],
timeout: PROCESS_START_TIMEOUT_MS,
killSignal: "SIGKILL"
}).trim();
const startedAtMs = Date.parse(`${startedAt} UTC`);
return Number.isFinite(startedAtMs) ? Math.floor(startedAtMs / 1e3) : null;
} catch {
return null;
}
}
/** Read the Linux procfs start identity used by Linux-owned runtime state. */
function getProcessStartTime(pid) {
if (!isValidPid(pid) || process.platform !== "linux") return null;
try {
const stat = fs.readFileSync(`/proc/${pid}/stat`, "utf8");
const commEndIndex = stat.lastIndexOf(")");
if (commEndIndex < 0) return null;
const fields = stat.slice(commEndIndex + 1).trimStart().split(/\s+/);
const starttime = Number(fields[19]);
return Number.isInteger(starttime) && starttime >= 0 ? starttime : null;
} catch {
return null;
}
}
/** Read a cross-platform process identity for filesystem lock ownership. */
function getFileLockProcessStartTime(pid) {
if (!isValidPid(pid)) return null;
const isSelf = pid === process.pid;
if (isSelf && selfStartTime !== null) return selfStartTime;
const startTime = process.platform === "darwin" ? getDarwinProcessStartTime(pid) : process.platform === "win32" ? readWindowsProcessStartTimeSync(pid) : getProcessStartTime(pid);
if (isSelf && startTime !== null) selfStartTime = startTime;
return startTime;
}
//#endregion
export { isPidDefinitelyDead as i, getProcessStartTime as n, isPidAlive as r, getFileLockProcessStartTime as t };