From fe92e71f7d3629fcea4e804fcfd9cec41e5fb76d Mon Sep 17 00:00:00 2001 From: Joni Shkurti Date: Thu, 9 Oct 2014 17:28:29 +0200 Subject: [PATCH] treekill implemented --- lib/God/Methods.js | 3 +- lib/TreeKill.js | 109 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 lib/TreeKill.js diff --git a/lib/God/Methods.js b/lib/God/Methods.js index 7b277c5d0..80461e412 100644 --- a/lib/God/Methods.js +++ b/lib/God/Methods.js @@ -7,6 +7,7 @@ */ var p = require('path'); var Common = require('../Common'); +var treekill = require('../TreeKill'); /** * Description * @method exports @@ -210,7 +211,7 @@ module.exports = function(God) { if (!pid) return cb({msg : 'no pid passed or null'}); try { - process.kill(pid, 'SIGINT'); + treekill(pid); } catch(e) { console.error('%s pid can not be killed', pid, e); return cb({type : 'kill', msg : pid + ' can not be killed'}); diff --git a/lib/TreeKill.js b/lib/TreeKill.js new file mode 100644 index 000000000..f3066d0e9 --- /dev/null +++ b/lib/TreeKill.js @@ -0,0 +1,109 @@ +/**! + * treekill - index.js + * + * Copyright(c) fengmk2 and other contributors. + * MIT Licensed + * + * Authors: + * fengmk2 (http://fengmk2.github.com) + * + * Github: + * https://github.com/node-modules/treekill + */ + +/** + * Module dependencies. + */ + +var childProcess = require('child_process'); +var spawn = childProcess.spawn; +var exec = childProcess.exec; +var isWindows = process.platform === 'win32'; +var isDarwin = process.platform === 'darwin'; + +module.exports = treekill; + +function treekill(pid, signal, callback) { + if (typeof signal === 'function') { + callback = signal; + signal = null; + } + + if (isWindows) { + exec('taskkill /pid ' + pid + ' /T /F'); + } else { + var tree = {}; + tree[pid] = []; + var pidsToProcess = {}; + pidsToProcess[pid] = 1; + buildProcessTree(pid, tree, pidsToProcess, function () { + killAll(tree, signal); + if (typeof callback === 'function') { + callback(); + } + }); + } +} + +function killAll(tree, signal) { + var killed = {}; + Object.keys(tree).forEach(function (pid) { + tree[pid].forEach(function (pidpid) { + if (!killed[pidpid]) { + killPid(pidpid, signal); + killed[pidpid] = 1; + } + }); + if (!killed[pid]) { + killPid(pid, signal); + killed[pid] = 1; + } + }); +} + +function killPid(pid, signal) { + try { + process.kill(parseInt(pid), signal); + } catch (err) { + if (err.code !== 'ESRCH') { + throw err; + } + } +} + +function buildProcessTree(ppid, tree, pidsToProcess, cb) { + var cmd = 'ps -e -o pid,ppid'; + ppid = String(ppid); + exec(cmd, function (err, stdout, stderr) { + if (err) { + console.log(stderr); + throw err; + } + var lines = stdout.toString().split('\n'); + lines = lines.map(function (line) { + return line.trim().split(/ +/).map(function (item) { + return item.trim(); + }); + }); + delete pidsToProcess[ppid]; + + var pids = []; + for (var i = 0; i < lines.length; i++) { + var item = lines[i]; + if (item[1] === ppid) { + pids.push(parseInt(item[0])); + } + } + + if (pids.length === 0 && Object.keys(pidsToProcess).length === 0) { + return cb(); + } + + pids.forEach(function (pid) { + tree[ppid].push(pid); + tree[pid] = []; + pidsToProcess[pid] = 1; + buildProcessTree(pid, tree, pidsToProcess, cb); + }); + }); +}