← Files RivetARCHIVED FILE

node_modules/rivet-design/dist/services/stopRuntimeProcess.js

3.35 KB · Nov 7, 2026 · 13:16 UTC

↓ Download file

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.stopRuntimeProcess = exports.runtimeProcessIdentity = void 0;
const promises_1 = require("timers/promises");
const pid_1 = require("../utils/pid");
const child_process_1 = require("child_process");
const subprocessEnvironment_1 = require("../utils/subprocessEnvironment");
const errnoCode_1 = require("../utils/errnoCode");
const SHUTDOWN_TIMEOUT_MS = 10_000;
const EXIT_POLL_MS = 100;
const FORCED_EXIT_TIMEOUT_MS = 2_000;
const IDENTITY_TIMEOUT_MS = 3_000;
const runtimeProcessIdentity = (pid) => {
    if (!Number.isSafeInteger(pid) || pid <= 0)
        throw new Error('Invalid runtime PID.');
    try {
        const command = process.platform === 'win32' ? 'powershell.exe' : 'ps';
        const args = process.platform === 'win32'
            ? [
                '-NoProfile',
                '-NonInteractive',
                '-Command',
                `(Get-Process -Id ${pid}).StartTime.ToUniversalTime().ToString('o')`,
            ]
            : ['-p', String(pid), '-o', 'lstart='];
        const identity = (0, child_process_1.execFileSync)(command, args, {
            encoding: 'utf8',
            timeout: IDENTITY_TIMEOUT_MS,
            env: (0, subprocessEnvironment_1.subprocessEnvironment)('verifier'),
            stdio: ['ignore', 'pipe', 'pipe'],
        }).trim();
        if (!identity)
            throw new Error(`Could not read the identity of Rivet process ${pid}.`);
        return identity;
    }
    catch (error) {
        if (!(0, pid_1.isPidAlive)(pid))
            return null;
        throw error;
    }
};
exports.runtimeProcessIdentity = runtimeProcessIdentity;
const stopRuntimeProcess = async ({ pid, isOwned, timeoutMs = SHUTDOWN_TIMEOUT_MS, }) => {
    const identity = (0, exports.runtimeProcessIdentity)(pid);
    let isVerified = false;
    const waitForExit = async (waitMs) => {
        const deadline = Date.now() + waitMs;
        while ((0, pid_1.isPidAlive)(pid)) {
            if (Date.now() >= deadline)
                return false;
            await (0, promises_1.setTimeout)(EXIT_POLL_MS);
        }
        return true;
    };
    const signal = async (value) => {
        if (!(0, pid_1.isPidAlive)(pid))
            return;
        if (pid === process.pid)
            throw new Error(`Cannot verify ownership of Rivet process ${pid}.`);
        if (!isVerified && !(await isOwned())) {
            if (await waitForExit(timeoutMs))
                return;
            throw new Error(`Cannot verify ownership of Rivet process ${pid}.`);
        }
        if (identity === null || (0, exports.runtimeProcessIdentity)(pid) !== identity) {
            if (await waitForExit(timeoutMs))
                return;
            throw new Error(`The identity of Rivet process ${pid} changed during shutdown.`);
        }
        isVerified = true;
        try {
            process.kill(pid, value);
        }
        catch (error) {
            if ((0, errnoCode_1.errnoCode)(error) !== 'ESRCH')
                throw error;
        }
    };
    await signal('SIGTERM');
    if (await waitForExit(timeoutMs))
        return;
    await signal('SIGKILL');
    if (!(await waitForExit(FORCED_EXIT_TIMEOUT_MS)))
        throw new Error(`Rivet process ${pid} did not exit after forced shutdown.`);
};
exports.stopRuntimeProcess = stopRuntimeProcess;
//# sourceMappingURL=stopRuntimeProcess.js.map

SHA-256: 61969c82724dce3d3a1333dc92314e2576800af252c1c9fa0d8c008dbd88d1a3