From 4dbf68bf396665e6b2820ca065da37818e4f26be Mon Sep 17 00:00:00 2001 From: jub3i Date: Mon, 11 May 2015 09:36:59 +0200 Subject: [PATCH 1/9] removed attaching 'exit' event handler to avoid race condition, also removed execution bit from files --- README.md | 0 index.js | 8 +++----- package.json | 0 3 files changed, 3 insertions(+), 5 deletions(-) mode change 100755 => 100644 README.md mode change 100755 => 100644 index.js mode change 100755 => 100644 package.json diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/index.js b/index.js old mode 100755 new mode 100644 index 783d525..85d3efc --- a/index.js +++ b/index.js @@ -1,7 +1,6 @@ var childProcess = require('child_process'); var spawn = childProcess.spawn; var exec = childProcess.exec; -var once = require('once'); var isWindows = process.platform === 'win32'; module.exports = function (pid, signal, callback) { @@ -63,7 +62,7 @@ function buildProcessTree (parentPid, tree, pidsToProcess, cb) { allData += data; }); - var onExitClose = once(function (code) { + var onClose = function (code) { delete pidsToProcess[parentPid]; if (code != 0) { @@ -93,8 +92,7 @@ function buildProcessTree (parentPid, tree, pidsToProcess, cb) { pidsToProcess[pid] = 1; buildProcessTree(pid, tree, pidsToProcess, cb); }); - }); + }; - ps.on('exit', onExitClose); - ps.on('close', onExitClose); + ps.on('close', onClose); } diff --git a/package.json b/package.json old mode 100755 new mode 100644 From 4d22f2bbe602a66b7df71e48c50361821edf24e5 Mon Sep 17 00:00:00 2001 From: jub3i Date: Mon, 11 May 2015 09:59:03 +0200 Subject: [PATCH 2/9] removed once from package.json deps --- package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/package.json b/package.json index e588032..549d1ea 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,6 @@ "url" : "git://github.com/pkrumins/node-tree-kill.git" }, "homepage" : "https://github.com/pkrumins/node-tree-kill", - "dependencies" : { - "once" : "1.1.1" - }, "keywords" : [ "tree", "trees", From 14bee4e0f5bd5d2f4d4255ca4ea1bb9f6a630aeb Mon Sep 17 00:00:00 2001 From: William Hilton Date: Mon, 11 May 2015 15:30:44 -0400 Subject: [PATCH 3/9] Organize for better OS-specific implementations. --- index.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 783d525..2282e01 100755 --- a/index.js +++ b/index.js @@ -2,21 +2,26 @@ var childProcess = require('child_process'); var spawn = childProcess.spawn; var exec = childProcess.exec; var once = require('once'); -var isWindows = process.platform === 'win32'; module.exports = function (pid, signal, callback) { - if (isWindows) { + var tree = {}; + var pidsToProcess = {}; + + switch (process.platform) { + case 'win32': exec('taskkill /pid ' + pid + ' /T /F', callback); - } else { - var tree = {}; + break; + case 'darwin': + break; + case 'sunos': + break; + default: // Linux tree[pid] = []; - var pidsToProcess = {}; pidsToProcess[pid] = 1; buildProcessTree(pid, tree, pidsToProcess, function () { try { killAll(tree, signal); - } - catch (err) { + } catch (err) { if (callback) { return callback(err); } else { @@ -27,8 +32,9 @@ module.exports = function (pid, signal, callback) { return callback(); } }); + break; } -} +}; function killAll (tree, signal) { var killed = {}; From 9331318df7167678253139904cb4a0c256cce21e Mon Sep 17 00:00:00 2001 From: William Hilton Date: Mon, 11 May 2015 15:58:30 -0400 Subject: [PATCH 4/9] Move callback try / catch boilerplate into killAll for better code re-use. --- index.js | 60 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/index.js b/index.js index 2282e01..9052133 100755 --- a/index.js +++ b/index.js @@ -6,50 +6,56 @@ var once = require('once'); module.exports = function (pid, signal, callback) { var tree = {}; var pidsToProcess = {}; + tree[pid] = []; + pidsToProcess[pid] = 1; switch (process.platform) { case 'win32': exec('taskkill /pid ' + pid + ' /T /F', callback); break; case 'darwin': + buildProcessTreeDarwin(pid, tree, pidsToProcess, function () { + killAll(tree, signal, callback); + }); break; case 'sunos': + buildProcessTreeSunOS(pid, tree, pidsToProcess, function () { + killAll(tree, signal, callback); + }); break; default: // Linux - tree[pid] = []; - pidsToProcess[pid] = 1; buildProcessTree(pid, tree, pidsToProcess, function () { - try { - killAll(tree, signal); - } catch (err) { - if (callback) { - return callback(err); - } else { - throw err; - } - } - if (callback) { - return callback(); - } + killAll(tree, signal, callback); }); break; } }; -function killAll (tree, signal) { +function killAll (tree, signal, callback) { var killed = {}; - Object.keys(tree).forEach(function (pid) { - tree[pid].forEach(function (pidpid) { - if (!killed[pidpid]) { - killPid(pidpid, signal); - killed[pidpid] = 1; + try { + 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; } }); - if (!killed[pid]) { - killPid(pid, signal); - killed[pid] = 1; + } catch (err) { + if (callback) { + return callback(err); + } else { + throw err; } - }); + } + if (callback) { + return callback(); + } } function killPid(pid, signal) { @@ -104,3 +110,9 @@ function buildProcessTree (parentPid, tree, pidsToProcess, cb) { ps.on('exit', onExitClose); ps.on('close', onExitClose); } + +function buildProcessTreeDarwin (parentPid, tree, pidsToProcess, cb) { +} + +function buildProcessTreeSunOS (parentPid, tree, pidsToProcess, cb) { +} From 118677291cc122aafed17005494e38ded8dad547 Mon Sep 17 00:00:00 2001 From: William Hilton Date: Fri, 15 May 2015 18:33:43 -0400 Subject: [PATCH 5/9] First try at a unit test --- .npmignore | 1 + package.json | 71 +++++++++++++++++++++++++++------------------------- test/spin.js | 3 +++ test/test.js | 25 ++++++++++++++++++ 4 files changed, 66 insertions(+), 34 deletions(-) create mode 100644 .npmignore create mode 100644 test/spin.js create mode 100644 test/test.js diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/package.json b/package.json index 549d1ea..075c76b 100644 --- a/package.json +++ b/package.json @@ -1,37 +1,40 @@ { - "name" : "tree-kill", - "version" : "0.1.0", - "description" : "kill trees of processes", - "main" : "index.js", - "repository" : { - "type" : "git", - "url" : "git://github.com/pkrumins/node-tree-kill.git" + "name": "tree-kill", + "version": "0.1.0", + "description": "kill trees of processes", + "main": "index.js", + "repository": { + "type": "git", + "url": "git://github.com/pkrumins/node-tree-kill.git" + }, + "homepage": "https://github.com/pkrumins/node-tree-kill", + "keywords": [ + "tree", + "trees", + "process", + "processes", + "kill", + "signal" + ], + "author": { + "name": "Peteris Krumins", + "email": "peteris.krumins@gmail.com", + "url": "http://www.catonmat.net" + }, + "contributors": [ + { + "name": "Todd Wolfson", + "email": "todd@twolfson.com", + "url": "http://twolfson.com/" }, - "homepage" : "https://github.com/pkrumins/node-tree-kill", - "keywords" : [ - "tree", - "trees", - "process", - "processes", - "kill", - "signal" - ], - "author" : { - "name" : "Peteris Krumins", - "email" : "peteris.krumins@gmail.com", - "url" : "http://www.catonmat.net" - }, - "contributors" : [ - { - "name" : "Todd Wolfson", - "email" : "todd@twolfson.com", - "url" : "http://twolfson.com/" - }, - { - "name" : "William Hilton", - "email" : "wmhilton@gmail.com", - "url" : "http://wmhilton.com/" - } - ], - "license" : "MIT" + { + "name": "William Hilton", + "email": "wmhilton@gmail.com", + "url": "http://wmhilton.com/" + } + ], + "license": "MIT", + "devDependencies": { + "mocha": "^2.2.5" + } } diff --git a/test/spin.js b/test/spin.js new file mode 100644 index 0000000..5ad3269 --- /dev/null +++ b/test/spin.js @@ -0,0 +1,3 @@ +setInterval(function(){ + // Do nothing +}, 100); \ No newline at end of file diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..35d9875 --- /dev/null +++ b/test/test.js @@ -0,0 +1,25 @@ +var assert = require('assert'); +var fork = require('child_process').fork; +var kill = require('tree-kill'); + +describe('kill()', function(){ + it('should kill a process', function(done){ + var p = fork('./test/spin') + assert.ok(p.pid) + + p.on('exit', function(code, signal){ + assert.ok(code || signal, 'should return an exit code') + return done() + }); + kill(p.pid) + }) + + it('should call a callback', function(done){ + var p = fork('./test/spin') + assert.ok(p.pid) + + kill(p.pid, null, function() { + return done() + }) + }) +}) From ed81474648aa0a9e76abcb50dafe5c5068205fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabricio=20Matte=CC=81?= Date: Wed, 12 Aug 2015 19:32:08 -0300 Subject: [PATCH 6/9] add Darwin support; clean up --- index.js | 56 ++++++++++++++++++++++---------------------------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/index.js b/index.js index 8197acb..ae4174b 100755 --- a/index.js +++ b/index.js @@ -1,3 +1,5 @@ +'use strict'; + var childProcess = require('child_process'); var spawn = childProcess.spawn; var exec = childProcess.exec; @@ -13,17 +15,21 @@ module.exports = function (pid, signal, callback) { exec('taskkill /pid ' + pid + ' /T /F', callback); break; case 'darwin': - buildProcessTreeDarwin(pid, tree, pidsToProcess, function () { - killAll(tree, signal, callback); - }); - break; - case 'sunos': - buildProcessTreeSunOS(pid, tree, pidsToProcess, function () { + buildProcessTree(pid, tree, pidsToProcess, function (parentPid) { + return spawn('pgrep', ['-P', parentPid]); + }, function () { killAll(tree, signal, callback); }); break; + // case 'sunos': + // buildProcessTreeSunOS(pid, tree, pidsToProcess, function () { + // killAll(tree, signal, callback); + // }); + // break; default: // Linux - buildProcessTree(pid, tree, pidsToProcess, function () { + buildProcessTree(pid, tree, pidsToProcess, function (parentPid) { + return spawn('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid]); + }, function () { killAll(tree, signal, callback); }); break; @@ -66,8 +72,8 @@ function killPid(pid, signal) { } } -function buildProcessTree (parentPid, tree, pidsToProcess, cb) { - var ps = spawn('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid]); +function buildProcessTree (parentPid, tree, pidsToProcess, spawnChildProcessesList, cb) { + var ps = spawnChildProcessesList(parentPid); var allData = ''; ps.stdout.on('data', function (data) { var data = data.toString('ascii'); @@ -82,35 +88,17 @@ function buildProcessTree (parentPid, tree, pidsToProcess, cb) { if (Object.keys(pidsToProcess).length == 0) { cb(); } - return - } - - pids = []; - pid = ''; - for (i = 0; i < allData.length; i++) { - if (allData[i] == '\n') { - pids.push(parseInt(pid, 10)); - pid = ''; - continue; - } - if (allData[i] != ' ') { - pid += allData[i]; - } + return; } - pids.forEach(function (pid) { - tree[parentPid].push(pid) - tree[pid] = []; - pidsToProcess[pid] = 1; - buildProcessTree(pid, tree, pidsToProcess, cb); + allData.match(/\d+/g).forEach(function (pid) { + pid = parseInt(pid, 10); + tree[parentPid].push(pid); + tree[pid] = []; + pidsToProcess[pid] = 1; + buildProcessTree(pid, tree, pidsToProcess, spawnChildProcessesList, cb); }); }; ps.on('close', onClose); } - -function buildProcessTreeDarwin (parentPid, tree, pidsToProcess, cb) { -} - -function buildProcessTreeSunOS (parentPid, tree, pidsToProcess, cb) { -} From 7cb642d695ce0495ac472cd2402d5d4036e1af92 Mon Sep 17 00:00:00 2001 From: Will Hilton Date: Thu, 17 Sep 2015 20:09:09 -0400 Subject: [PATCH 7/9] Update README.md --- README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 99fe2a2..6bc17c7 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,22 @@ Tree Kill Kill all processes in the process tree, including the root process. -Example +Examples ======= -Kill all the children processes of the process with pid `1`, including the process with pid `1` itself: +Kill all the descendent processes of the process with pid `1`, including the process with pid `1` itself: +```js +var kill = require('tree-kill'); +kill(1); +``` + +Send a signal other than SIGTERM.: ```js var kill = require('tree-kill'); kill(1, 'SIGKILL'); ``` -Supports callbacks with error handling: +Run a callback when done killing the processes. Passes an error argument if there was an error. ```js var kill = require('tree-kill'); kill(1, 'SIGKILL', function(err) { @@ -20,7 +26,6 @@ kill(1, 'SIGKILL', function(err) { }); ``` - Methods ======= @@ -30,7 +35,9 @@ Sends signal `signal` to all children processes of the process with pid `pid`, i For Linux, this uses `ps -o pid --no-headers --ppid PID` to find the parent pids of `PID`. -For Windows, this uses `'taskkill /pid PID /T /F'` to kill the process tree. +For Darwin/OSX, this uses `pgrep -P PID` to find the parent pids of `PID`. + +For Windows, this uses `'taskkill /pid PID /T /F'` to kill the process tree. Note that on Windows, sending the different kinds of POSIX signals is not possible. Install ======= From 7ba7d1e5eb0d90718cf8ca09f7eeae7f996324fb Mon Sep 17 00:00:00 2001 From: Will Hilton Date: Thu, 17 Sep 2015 20:24:53 -0400 Subject: [PATCH 8/9] Add UltCombo to contributors @UltCombo do you want to be listed as a contributor? --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 075c76b..55a07fd 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,10 @@ "name": "William Hilton", "email": "wmhilton@gmail.com", "url": "http://wmhilton.com/" + }, + { + "name": "Fabrício Matté", + "url": "http://ultcombo.js.org/" } ], "license": "MIT", From f71809530f9fec776c962113b6b7d0b3ebd601c7 Mon Sep 17 00:00:00 2001 From: Will Hilton Date: Thu, 17 Sep 2015 20:30:33 -0400 Subject: [PATCH 9/9] Bump version number to a 1.0.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 55a07fd..4abcaeb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tree-kill", - "version": "0.1.0", + "version": "1.0.0", "description": "kill trees of processes", "main": "index.js", "repository": {