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)) )) }) }) }