diff --git a/scripts/terminateProcess.sh b/scripts/terminateProcess.sh new file mode 100755 index 000000000..9b068843f --- /dev/null +++ b/scripts/terminateProcess.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +terminateTree() { + for cpid in $(/usr/bin/pgrep -P $1); do + terminateTree $cpid + done + kill -9 $1 > /dev/null 2>&1 +} + +for pid in $*; do + terminateTree $pid +done diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts index b59c163d4..45061421e 100644 --- a/src/debugAdapter/goDebug.ts +++ b/src/debugAdapter/goDebug.ts @@ -9,7 +9,7 @@ import { DebugProtocol } from 'vscode-debugprotocol'; import { DebugSession, InitializedEvent, TerminatedEvent, ThreadEvent, StoppedEvent, OutputEvent, Thread, StackFrame, Scope, Source, Handles } from 'vscode-debugadapter'; import { readFileSync, existsSync, lstatSync } from 'fs'; import { basename, dirname } from 'path'; -import { spawn, ChildProcess } from 'child_process'; +import { spawn, ChildProcess, execSync, spawnSync } from 'child_process'; import { Client, RPCConnection } from 'json-rpc2'; import { getBinPathWithPreferredGopath } from '../goPath'; import * as logger from 'vscode-debug-logger'; @@ -307,7 +307,7 @@ class Delve { }); }); } else { - this.debugProcess.kill(); + killTree(this.debugProcess.pid); } } } @@ -759,4 +759,24 @@ function random(low: number, high: number): number { return Math.floor(Math.random() * (high - low) + low); } +function killTree(processId: number): void { + if (process.platform === 'win32') { + const TASK_KILL = 'C:\\Windows\\System32\\taskkill.exe'; + + // when killing a process in Windows its child processes are *not* killed but become root processes. + // Therefore we use TASKKILL.EXE + try { + execSync(`${TASK_KILL} /F /T /PID ${processId}`); + } catch (err) { + } + } else { + // on linux and OS X we kill all direct and indirect child processes as well + try { + const cmd = path.join(__dirname, '../../../scripts/terminateProcess.sh'); + spawnSync(cmd, [ processId.toString() ]); + } catch (err) { + } + } +} + DebugSession.run(GoDebugSession);