( processId: number, logger: ILogger, behavior = KillBehavior.Forceful, )
| 10 | * Kills the tree of processes starting at the given parent ID. |
| 11 | */ |
| 12 | export function killTree( |
| 13 | processId: number, |
| 14 | logger: ILogger, |
| 15 | behavior = KillBehavior.Forceful, |
| 16 | ): boolean { |
| 17 | if (behavior === KillBehavior.None) { |
| 18 | return true; |
| 19 | } |
| 20 | |
| 21 | if (process.platform === 'win32') { |
| 22 | const windir = process.env['WINDIR'] || 'C:\\Windows'; |
| 23 | const TASK_KILL = join(windir, 'System32', 'taskkill.exe'); |
| 24 | |
| 25 | // when killing a process in Windows its child processes are *not* killed but become root processes. |
| 26 | // Therefore we use TASKKILL.EXE |
| 27 | try { |
| 28 | execSync( |
| 29 | `${TASK_KILL} ${behavior === KillBehavior.Forceful ? '/F' : ''} /T /PID ${processId}`, |
| 30 | { stdio: 'pipe' }, |
| 31 | ); |
| 32 | return true; |
| 33 | } catch (err) { |
| 34 | logger.error(LogTag.RuntimeException, 'Error running taskkill.exe', err); |
| 35 | return false; |
| 36 | } |
| 37 | } else { |
| 38 | // on linux and OS X we kill all direct and indirect child processes as well |
| 39 | try { |
| 40 | const cmd = join(__dirname, './targets/node/terminateProcess.sh'); |
| 41 | const r = spawnSync('sh', [ |
| 42 | cmd, |
| 43 | processId.toString(), |
| 44 | behavior === KillBehavior.Forceful ? '9' : '15', |
| 45 | ]); |
| 46 | |
| 47 | if (r.stderr && r.status) { |
| 48 | logger.error(LogTag.RuntimeException, 'Error running terminateProcess', r); |
| 49 | return false; |
| 50 | } |
| 51 | |
| 52 | return true; |
| 53 | } catch (err) { |
| 54 | logger.error(LogTag.RuntimeException, 'Error running terminateProcess', err); |
| 55 | return false; |
| 56 | } |
| 57 | } |
| 58 | } |
no test coverage detected