Skip to content

Commit

Permalink
fix eclipse-theia#6767: don't reuse integrated terminal that has chil…
Browse files Browse the repository at this point in the history
…d processes

Signed-off-by: Cai Xuye <a1994846931931@gmail.com>
  • Loading branch information
a1994846931931 committed Dec 18, 2019
1 parent 4c4a1f2 commit de7816a
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 1 deletion.
8 changes: 7 additions & 1 deletion packages/debug/src/browser/debug-session.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,13 @@ export class DebugSession implements CompositeTreeElement {
}

protected async doCreateTerminal(options: TerminalWidgetOptions): Promise<TerminalWidget> {
let terminal = this.terminalServer.all.find(t => t.title.label === options.title || t.title.caption === options.title);
let terminal = undefined;
for (const t of this.terminalServer.all) {
if ((t.title.label === options.title || t.title.caption === options.title) && (await t.hasChildProcesses()) === false) {
terminal = t;
}
}

if (!terminal) {
terminal = await this.terminalServer.newTerminal(options);
await terminal.start();
Expand Down
5 changes: 5 additions & 0 deletions packages/terminal/src/browser/base/terminal-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ export abstract class TerminalWidget extends BaseWidget {
* Cleat terminal output.
*/
abstract clearOutput(): void;

/**
* Whether the terminal process has child processes.
*/
abstract hasChildProcesses(): Promise<boolean>;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions packages/terminal/src/browser/terminal-widget-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,10 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
this.term.clear();
}

async hasChildProcesses(): Promise<boolean> {
return this.shellTerminalServer.hasChildProcesses(await this.processId);
}

storeState(): object {
this.closeOnDispose = false;
return { terminalId: this.terminalId, titleLabel: this.title.label };
Expand Down
1 change: 1 addition & 0 deletions packages/terminal/src/common/shell-terminal-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { IBaseTerminalServer, IBaseTerminalServerOptions } from './base-terminal
export const IShellTerminalServer = Symbol('IShellTerminalServer');

export interface IShellTerminalServer extends IBaseTerminalServer {
hasChildProcesses(processId: number | undefined): Promise<boolean>;
}

export const shellTerminalPath = '/services/shell-terminal';
Expand Down
33 changes: 33 additions & 0 deletions packages/terminal/src/node/shell-terminal-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { IShellTerminalServerOptions } from '../common/shell-terminal-protocol';
import { BaseTerminalServer } from '../node/base-terminal-server';
import { ShellProcessFactory } from '../node/shell-process';
import { ProcessManager } from '@theia/process/lib/node';
import { isWindows } from '@theia/core/lib/common/os';
import * as cp from 'child_process';

@injectable()
export class ShellTerminalServer extends BaseTerminalServer {
Expand All @@ -41,4 +43,35 @@ export class ShellTerminalServer extends BaseTerminalServer {
return Promise.resolve(-1);
}
}

// copied and modified from https://github.com/microsoft/vscode/blob/4636be2b71c87bfb0bfe3c94278b447a5efcc1f1/src/vs/workbench/contrib/debug/node/terminals.ts#L50-L75
async hasChildProcesses(processId: number | undefined): Promise<boolean> {
if (processId) {
try {
// if shell has at least one child process, assume that shell is busy
if (isWindows) {
const result = cp.spawnSync('wmic', ['process', 'get', 'ParentProcessId']);
if (result.stdout) {
const pids = result.stdout.toString().split('\r\n');
return pids.some(p => parseInt(p) === processId);
}
} 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) {
return false;
} else {
return true;
}
}
}
} catch (e) {
// silently ignore
}
}
// fall back to safe side
return true;
}

}

0 comments on commit de7816a

Please sign in to comment.