const os = require("os"); const childProcess = require("child_process"); const psTree = require("ps-tree"); const streamToLogger = require("stream-to-logger"); module.exports = function runProcess(path, args, options) { if (options.logger != null) { options.logger.info(`Starting ${path}...`); } let proc = childProcess.spawn(path, args, options); if (options.logger != null) { proc.stdout.pipe(streamToLogger(options.logger.log)); proc.stderr.pipe(streamToLogger(options.logger.error)); } proc.on("error", (err) => { if (options.logger != null) { options.logger.error(err.stack); } }); proc.on("close", (code, signal) => { if (code != null) { options.logger.info(`${path} exited with code ${code.toString()}.`); } else if (signal != null) { options.logger.info(`${path} exited due to signal ${signal}.`); } else { options.logger.info(`${path} exited for an unknown reason.`); } }); let _kill = proc.kill.bind(proc); proc.kill = function(signal) { /* FIXME: Are other UNIX-y platforms also affected by the killing-children-of-children issue? And do they have `ps` with the same flags? */ if (os.platform() === "linux") { psTree(proc.pid, (err, children) => { if (err != null) { console.error(`WARN: Could not kill children of PID ${proc.pid}: ${err.message}`); console.error(err.stack); _kill(signal); } else { childProcess.execFile("kill", children.map((child) => child.PID), (err, stdout, stderr) => { _kill(signal); }); } }) } else { _kill(signal); } } return proc; }