diff --git a/actions/start.action.ts b/actions/start.action.ts index 93ba6ee82..9e649c833 100644 --- a/actions/start.action.ts +++ b/actions/start.action.ts @@ -3,6 +3,7 @@ import { spawn } from 'child_process'; import * as fs from 'fs'; import { join } from 'path'; import * as killProcess from 'tree-kill'; +import { treeKillSync as killProcessSync } from '../lib/utils/tree-kill'; import { Input } from '../commands'; import { getValueOrDefault } from '../lib/compiler/helpers/get-value-or-default'; import { Configuration } from '../lib/configuration'; @@ -84,7 +85,7 @@ export class StartAction extends BuildAction { let childProcessRef: any; process.on( 'exit', - () => childProcessRef && killProcess(childProcessRef.pid), + () => childProcessRef && killProcessSync(childProcessRef.pid), ); return () => { diff --git a/lib/utils/tree-kill.ts b/lib/utils/tree-kill.ts new file mode 100644 index 000000000..1852f84e9 --- /dev/null +++ b/lib/utils/tree-kill.ts @@ -0,0 +1,80 @@ +import { execSync } from 'child_process'; + +export function treeKillSync(pid: number, signal?: string | number): void { + if (process.platform === 'win32') { + execSync('taskkill /pid ' + pid + ' /T /F'); + return; + } + + const childs = getAllChilds(pid); + childs.forEach(function (pid) { + killPid(pid, signal); + }); + + killPid(pid, signal); + return; +} + +function getAllPid(): { + pid: number; + ppid: number; +}[] { + const rows = execSync('ps -A -o pid,ppid') + .toString() + .trim() + .split('\n') + .slice(1); + + return rows + .map(function (row) { + var parts = row.match(/\s*(\d+)\s*(\d+)/); + + if (parts === null) { + return null; + } + + return { + pid: Number(parts[1]), + ppid: Number(parts[2]), + }; + }) + .filter((input: null | undefined | T): input is T => { + return input != null; + }); +} + +function getAllChilds(pid: number) { + const allpid = getAllPid(); + + let ppidHash: { + [key: number]: number[]; + } = {}; + + let result: number[] = []; + + allpid.forEach(function (item) { + ppidHash[item.ppid] = ppidHash[item.ppid] || []; + ppidHash[item.ppid].push(item.pid); + }); + + const find = function (pid: number) { + ppidHash[pid] = ppidHash[pid] || []; + ppidHash[pid].forEach(function (childPid) { + result.push(childPid); + find(childPid); + }); + }; + + find(pid); + return result; +} + +function killPid(pid: number, signal?: string | number) { + try { + process.kill(pid, signal); + } catch (err) { + if (err.code !== 'ESRCH') { + throw err; + } + } +}