UNPKG

@gguf/claw

Version:

WhatsApp gateway CLI (Baileys web) with Pi RPC agent

96 lines (94 loc) 3.14 kB
import { _ as sleep } from "./utils-DX85MiPR.js"; import { p as resolveLsofCommandSync } from "./errors-CZ9opC6L.js"; import { execFileSync } from "node:child_process"; //#region src/cli/ports.ts function parseLsofOutput(output) { const lines = output.split(/\r?\n/).filter(Boolean); const results = []; let current = {}; for (const line of lines) if (line.startsWith("p")) { if (current.pid) results.push(current); current = { pid: Number.parseInt(line.slice(1), 10) }; } else if (line.startsWith("c")) current.command = line.slice(1); if (current.pid) results.push(current); return results; } function listPortListeners(port) { try { return parseLsofOutput(execFileSync(resolveLsofCommandSync(), [ "-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-FpFc" ], { encoding: "utf-8" })); } catch (err) { const status = err.status; if (err.code === "ENOENT") throw new Error("lsof not found; required for --force", { cause: err }); if (status === 1) return []; throw err instanceof Error ? err : new Error(String(err)); } } function forceFreePort(port) { const listeners = listPortListeners(port); for (const proc of listeners) try { process.kill(proc.pid, "SIGTERM"); } catch (err) { throw new Error(`failed to kill pid ${proc.pid}${proc.command ? ` (${proc.command})` : ""}: ${String(err)}`, { cause: err }); } return listeners; } function killPids(listeners, signal) { for (const proc of listeners) try { process.kill(proc.pid, signal); } catch (err) { throw new Error(`failed to kill pid ${proc.pid}${proc.command ? ` (${proc.command})` : ""}: ${String(err)}`, { cause: err }); } } async function forceFreePortAndWait(port, opts = {}) { const timeoutMs = Math.max(opts.timeoutMs ?? 1500, 0); const intervalMs = Math.max(opts.intervalMs ?? 100, 1); const sigtermTimeoutMs = Math.min(Math.max(opts.sigtermTimeoutMs ?? 600, 0), timeoutMs); const killed = forceFreePort(port); if (killed.length === 0) return { killed, waitedMs: 0, escalatedToSigkill: false }; let waitedMs = 0; const triesSigterm = intervalMs > 0 ? Math.ceil(sigtermTimeoutMs / intervalMs) : 0; for (let i = 0; i < triesSigterm; i++) { if (listPortListeners(port).length === 0) return { killed, waitedMs, escalatedToSigkill: false }; await sleep(intervalMs); waitedMs += intervalMs; } if (listPortListeners(port).length === 0) return { killed, waitedMs, escalatedToSigkill: false }; killPids(listPortListeners(port), "SIGKILL"); const remainingBudget = Math.max(timeoutMs - waitedMs, 0); const triesSigkill = intervalMs > 0 ? Math.ceil(remainingBudget / intervalMs) : 0; for (let i = 0; i < triesSigkill; i++) { if (listPortListeners(port).length === 0) return { killed, waitedMs, escalatedToSigkill: true }; await sleep(intervalMs); waitedMs += intervalMs; } const still = listPortListeners(port); if (still.length === 0) return { killed, waitedMs, escalatedToSigkill: true }; throw new Error(`port ${port} still has listeners after --force: ${still.map((p) => p.pid).join(", ")}`); } //#endregion export { forceFreePortAndWait as n, forceFreePort as t };