UNPKG

2.59 kBJavaScriptView Raw
1var childProcess = require('child_process');
2var spawn = childProcess.spawn;
3var exec = childProcess.exec;
4var once = require('once');
5var isWindows = process.platform === 'win32';
6
7module.exports = function (pid, signal, callback) {
8 if (isWindows) {
9 exec('taskkill /pid ' + pid + ' /T /F', callback);
10 } else {
11 var tree = {};
12 tree[pid] = [];
13 var pidsToProcess = {};
14 pidsToProcess[pid] = 1;
15 buildProcessTree(pid, tree, pidsToProcess, function () {
16 try {
17 killAll(tree, signal);
18 }
19 catch (err) {
20 if (callback) {
21 return callback(err);
22 } else {
23 throw err;
24 }
25 }
26 if (callback) {
27 return callback();
28 }
29 });
30 }
31}
32
33function killAll (tree, signal) {
34 var killed = {};
35 Object.keys(tree).forEach(function (pid) {
36 tree[pid].forEach(function (pidpid) {
37 if (!killed[pidpid]) {
38 killPid(pidpid, signal);
39 killed[pidpid] = 1;
40 }
41 });
42 if (!killed[pid]) {
43 killPid(pid, signal);
44 killed[pid] = 1;
45 }
46 });
47}
48
49function killPid(pid, signal) {
50 try {
51 process.kill(pid, signal);
52 }
53 catch (err) {
54 if (err.code !== 'ESRCH') throw err;
55 }
56}
57
58function buildProcessTree (parentPid, tree, pidsToProcess, cb) {
59 var ps = spawn('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid]);
60 var allData = '';
61 ps.stdout.on('data', function (data) {
62 var data = data.toString('ascii');
63 allData += data;
64 });
65
66 var onExitClose = once(function (code) {
67 delete pidsToProcess[parentPid];
68
69 if (code != 0) {
70 // no more parent processes
71 if (Object.keys(pidsToProcess).length == 0) {
72 cb();
73 }
74 return
75 }
76
77 pids = [];
78 pid = '';
79 for (i = 0; i < allData.length; i++) {
80 if (allData[i] == '\n') {
81 pids.push(parseInt(pid, 10));
82 pid = '';
83 continue;
84 }
85 if (allData[i] != ' ') {
86 pid += allData[i];
87 }
88 }
89
90 pids.forEach(function (pid) {
91 tree[parentPid].push(pid)
92 tree[pid] = [];
93 pidsToProcess[pid] = 1;
94 buildProcessTree(pid, tree, pidsToProcess, cb);
95 });
96 });
97
98 ps.on('exit', onExitClose);
99 ps.on('close', onExitClose);
100}