diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index 474c69813d1..f4a7d7eed8f 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -340,46 +340,38 @@ export class ExtHostDebugService implements IExtHostDebugService, ExtHostDebugSe }); } - return new Promise(resolve => { - if (this._integratedTerminalInstance) { - this._integratedTerminalInstance.processId.then(pid => { - resolve(hasChildProcesses(pid)); - }, err => { - resolve(true); - }); - } else { - resolve(true); - } - }).then(async needNewTerminal => { + let needNewTerminal = true; // be pessimistic + if (this._integratedTerminalInstance) { + const pid = await this._integratedTerminalInstance.processId; + needNewTerminal = await hasChildProcesses(pid); // if no processes running in terminal reuse terminal + } - const configProvider = await this._configurationService.getConfigProvider(); - const shell = this._terminalService.getDefaultShell(true, configProvider); + const configProvider = await this._configurationService.getConfigProvider(); + const shell = this._terminalService.getDefaultShell(true, configProvider); - if (needNewTerminal || !this._integratedTerminalInstance) { - const options: vscode.TerminalOptions = { - shellPath: shell, - // shellArgs: this._terminalService._getDefaultShellArgs(configProvider), - cwd: args.cwd, - name: args.title || nls.localize('debug.terminal.title', "debuggee"), - env: args.env - }; - delete args.cwd; - delete args.env; - this._integratedTerminalInstance = this._terminalService.createTerminalFromOptions(options); - } - const terminal: vscode.Terminal = this._integratedTerminalInstance; + if (needNewTerminal || !this._integratedTerminalInstance) { - terminal.show(); + const options: vscode.TerminalOptions = { + shellPath: shell, + // shellArgs: this._terminalService._getDefaultShellArgs(configProvider), + cwd: args.cwd, + name: args.title || nls.localize('debug.terminal.title', "debuggee"), + env: args.env + }; + delete args.cwd; + delete args.env; + this._integratedTerminalInstance = this._terminalService.createTerminalFromOptions(options); + } - return this._integratedTerminalInstance.processId.then(shellProcessId => { + const terminal = this._integratedTerminalInstance; - const command = prepareCommand(args, shell, configProvider); + terminal.show(); - terminal.sendText(command, true); + const shellProcessId = await this._integratedTerminalInstance.processId; + const command = prepareCommand(args, shell, configProvider); + terminal.sendText(command, true); - return shellProcessId; - }); - }); + return shellProcessId; } else if (args.kind === 'external') { diff --git a/src/vs/workbench/contrib/debug/node/terminals.ts b/src/vs/workbench/contrib/debug/node/terminals.ts index 315658072d1..7142a363971 100644 --- a/src/vs/workbench/contrib/debug/node/terminals.ts +++ b/src/vs/workbench/contrib/debug/node/terminals.ts @@ -29,34 +29,49 @@ export function runInExternalTerminal(args: DebugProtocol.RunInTerminalRequestAr } } -export function hasChildProcesses(processId: number): boolean { - if (processId) { - try { - // if shell has at least one child process, assume that shell is busy - if (env.isWindows) { - const result = cp.spawnSync('wmic', ['process', 'get', 'ParentProcessId']); - if (result.stdout) { - const pids = result.stdout.toString().split('\r\n'); - if (!pids.some(p => parseInt(p) === processId)) { - return false; - } - } - } else { - const result = cp.spawnSync('/usr/bin/pgrep', ['-lP', String(processId)]); - if (result.stdout) { - const r = result.stdout.toString().trim(); - if (r.length === 0 || r.indexOf(' tmux') >= 0) { // ignore 'tmux'; see #43683 - return false; - } - } - } +function spawnAsPromised(command: string, args: string[]): Promise { + return new Promise((resolve, reject) => { + let stdout = ''; + const child = cp.spawn(command, args); + if (child.pid) { + child.stdout.on('data', (data: Buffer) => { + stdout += data.toString(); + }); } - catch (e) { - // silently ignore + child.on('error', err => { + reject(err); + }); + child.on('close', code => { + resolve(stdout); + }); + }); +} + +export function hasChildProcesses(processId: number): Promise { + if (processId) { + // if shell has at least one child process, assume that shell is busy + if (env.isWindows) { + return spawnAsPromised('wmic', ['process', 'get', 'ParentProcessId']).then(stdout => { + const pids = stdout.split('\r\n'); + return pids.some(p => parseInt(p) === processId); + }, error => { + return true; + }); + } else { + return spawnAsPromised('/usr/bin/pgrep', ['-lP', String(processId)]).then(stdout => { + const r = stdout.trim(); + if (r.length === 0 || r.indexOf(' tmux') >= 0) { // ignore 'tmux'; see #43683 + return false; + } else { + return true; + } + }, error => { + return true; + }); } } // fall back to safe side - return true; + return Promise.resolve(true); } const enum ShellType { cmd, powershell, bash }