From 6dfe3250fcf2a7d45e4eeb1b2c55bacbd712372d Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Tue, 31 May 2016 06:19:41 +0200 Subject: [PATCH] Fix exit logging to also support signals, and recursively kill child processes on Linux by default to avoid the children-of-children problem --- package.json | 1 + src/index.js | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e2cd0b1..f5561de 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "author": "Sven Slootweg", "license": "WTFPL", "dependencies": { + "ps-tree": "^1.0.1", "stream-to-logger": "0.0.1" }, "devDependencies": { diff --git a/src/index.js b/src/index.js index 4d3a9df..eaccd8c 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,6 @@ +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) { @@ -19,9 +21,35 @@ module.exports = function runProcess(path, args, options) { } }); - proc.on("close", (code) => { - options.logger.info(`${path} exited with code ${code.toString()}.`); + 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; }