eltro/lib/kill.mjs

61 lines
1.4 KiB
JavaScript
Raw Normal View History

import { promisify } from 'util'
import { spawn, exec } from 'child_process'
const execPromise = promisify(exec)
export default function kill(pid, signal) {
let pids = new Set([pid])
let getSpawn = null
switch (process.platform) {
case 'win32':
return execPromise('taskkill /pid ' + pid + ' /T /F').then(() => pids)
case 'darwin':
getSpawn = function(parentPid) {
return spawn('pgrep', ['-P', parentPid])
}
break
default:
getSpawn = function (parentPid) {
return spawn('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid])
}
break
}
return buildTree(pids, getSpawn, pid)
.then(function() {
for (let pid of pids) {
try {
process.kill(pid, signal)
} catch (err) {
if (err.code !== 'ESRCH') throw err;
}
}
return pids
})
}
function buildTree(allPids, spawnGetChildren, parentPid) {
allPids.add(parentPid)
let ps = spawnGetChildren(parentPid)
let data = ''
ps.stdout.on('data', function(buf) {
data += buf.toString('ascii')
})
return new Promise(function(res) {
ps.on('close', function(code) {
// Check if we got error code (usually means empty results)
if (code !== 0) return res()
res(Promise.all(
data.match(/\d+/g)
.map(Number)
.filter(pid => !allPids.has(pid))
.map(buildTree.bind(this, allPids, spawnGetChildren))
))
})
})
}