UNPKG

firebase-tools

Version:
113 lines (112 loc) • 3.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DEFAULT_VENV_DIR = void 0; exports.virtualEnvCmd = virtualEnvCmd; exports.runWithVirtualEnv = runWithVirtualEnv; exports.killProcessTree = killProcessTree; exports.trackVirtualEnvChild = trackVirtualEnvChild; exports.untrackVirtualEnvChild = untrackVirtualEnvChild; const os = require("os"); const path = require("path"); const cross_spawn_1 = require("cross-spawn"); const cp = require("child_process"); const logger_1 = require("../logger"); const utils_1 = require("../utils"); const error_1 = require("../error"); exports.DEFAULT_VENV_DIR = "venv"; function virtualEnvCmd(cwd, venvDir) { const activateScriptPath = utils_1.IS_WINDOWS ? ["Scripts", "activate.bat"] : ["bin", "activate"]; const venvActivate = `"${path.join(cwd, venvDir, ...activateScriptPath)}"`; return { command: utils_1.IS_WINDOWS ? venvActivate : ".", args: utils_1.IS_WINDOWS ? [] : [venvActivate], }; } function runWithVirtualEnv(commandAndArgs, cwd, envs, spawnOpts = {}, venvDir = exports.DEFAULT_VENV_DIR) { const { command, args } = virtualEnvCmd(cwd, venvDir); args.push("&&", ...commandAndArgs); logger_1.logger.debug(`Running command with virtualenv: command=${command}, args=${JSON.stringify(args)}`); return (0, cross_spawn_1.spawn)(command, args, { shell: true, cwd, stdio: "pipe", ...spawnOpts, env: { ...process.env, ...envs }, }); } function killProcessTree(pid) { if (!pid || pid <= 0) { return; } if (utils_1.IS_WINDOWS) { const result = cp.spawnSync("taskkill", ["/pid", pid.toString(), "/T", "/F"]); if (result.error || result.status !== 0) { logger_1.logger.debug(`taskkill on pid ${pid} exited with ${String(result.status)}: ` + `${result.error?.message ?? result.stderr?.toString().trim() ?? ""}`); } return; } try { process.kill(-pid, "SIGKILL"); } catch (e) { logger_1.logger.debug(`Failed to kill process group ${pid}: ${(0, error_1.getErrMsg)(e)}`); } } const CLEANUP_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP", "SIGQUIT"]; const trackedChildren = new Set(); const signalHandlers = new Map(); function reRaise(signal) { try { process.kill(process.pid, signal); } catch (e) { logger_1.logger.debug(`Could not re-raise ${signal}, exiting instead: ${(0, error_1.getErrMsg)(e)}`); process.exit(128 + (os.constants.signals[signal] ?? 0)); } } function killAllTrackedChildren() { for (const child of trackedChildren) { if (child.pid && child.exitCode === null && child.signalCode === null) { killProcessTree(child.pid); } } trackedChildren.clear(); } function removeCleanupHandlers() { if (!signalHandlers.size) { return; } process.removeListener("exit", killAllTrackedChildren); for (const [signal, handler] of signalHandlers) { process.removeListener(signal, handler); } signalHandlers.clear(); } function addCleanupHandlers() { if (signalHandlers.size) { return; } process.on("exit", killAllTrackedChildren); for (const signal of CLEANUP_SIGNALS) { const handler = () => { killAllTrackedChildren(); removeCleanupHandlers(); if (process.listenerCount(signal) === 0) { reRaise(signal); } }; signalHandlers.set(signal, handler); process.on(signal, handler); } } function trackVirtualEnvChild(child) { trackedChildren.add(child); addCleanupHandlers(); } function untrackVirtualEnvChild(child) { trackedChildren.delete(child); if (!trackedChildren.size) { removeCleanupHandlers(); } }