提交 dab1430b 编写于 作者: D Daniel Imms

Shutdown exthost terminal processes gracefully

Fixes #107444
上级 b241d4cd
......@@ -13,7 +13,7 @@ import { ITerminalChildProcess, ITerminalDimensions, EXT_HOST_CREATION_DELAY, IT
import { timeout } from 'vs/base/common/async';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { TerminalDataBufferer } from 'vs/workbench/contrib/terminal/common/terminalDataBuffering';
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
import { Disposable as VSCodeDisposable, EnvironmentVariableMutatorType } from './extHostTypes';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
......@@ -22,7 +22,7 @@ import { NotSupportedError } from 'vs/base/common/errors';
import { serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
export interface IExtHostTerminalService extends ExtHostTerminalServiceShape {
export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, IDisposable {
readonly _serviceBrand: undefined;
......@@ -306,14 +306,14 @@ interface ICachedLinkEntry {
link: vscode.TerminalLink;
}
export abstract class BaseExtHostTerminalService implements IExtHostTerminalService, ExtHostTerminalServiceShape {
export abstract class BaseExtHostTerminalService extends Disposable implements IExtHostTerminalService, ExtHostTerminalServiceShape {
readonly _serviceBrand: undefined;
protected _proxy: MainThreadTerminalServiceShape;
protected _activeTerminal: ExtHostTerminal | undefined;
protected _terminals: ExtHostTerminal[] = [];
protected _terminalProcesses: { [id: number]: ITerminalChildProcess } = {};
protected _terminalProcesses: Map<number, ITerminalChildProcess> = new Map();
protected _terminalProcessDisposables: { [id: number]: IDisposable } = {};
protected _extensionTerminalAwaitingStart: { [id: number]: { initialDimensions: ITerminalDimensionsDto | undefined } | undefined } = {};
protected _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal | undefined> } = {};
......@@ -342,6 +342,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
supportsProcesses: boolean,
@IExtHostRpcService extHostRpc: IExtHostRpcService
) {
super();
this._proxy = extHostRpc.getProxy(MainContext.MainThreadTerminalService);
this._bufferer = new TerminalDataBufferer(this._proxy.$sendProcessData);
this._onDidWriteTerminalData = new Emitter<vscode.TerminalDataWriteEvent>({
......@@ -349,6 +350,13 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
onLastListenerRemove: () => this._proxy.$stopSendingDataEvents()
});
this._proxy.$registerProcessSupport(supportsProcesses);
this._register({
dispose: () => {
for (const [_, terminalProcess] of this._terminalProcesses) {
terminalProcess.shutdown(true);
}
}
});
}
public abstract createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal;
......@@ -421,11 +429,9 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
public async $acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): Promise<void> {
await this._getTerminalByIdEventually(id);
if (this._terminalProcesses[id]) {
// Extension pty terminal only - when virtual process resize fires it means that the
// terminal's maximum dimensions changed
this._terminalProcesses[id]?.resize(cols, rows);
}
// Extension pty terminal only - when virtual process resize fires it means that the
// terminal's maximum dimensions changed
this._terminalProcesses.get(id)?.resize(cols, rows);
}
public async $acceptTerminalTitleChange(id: number, name: string): Promise<void> {
......@@ -497,8 +503,9 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
});
}
if (this._terminalProcesses[id]) {
(this._terminalProcesses[id] as ExtHostPseudoterminal).startSendingEvents(initialDimensions);
const terminalProcess = this._terminalProcesses.get(id);
if (terminalProcess) {
(terminalProcess as ExtHostPseudoterminal).startSendingEvents(initialDimensions);
} else {
// Defer startSendingEvents call to when _setupExtHostProcessListeners is called
this._extensionTerminalAwaitingStart[id] = { initialDimensions };
......@@ -520,7 +527,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
if (p.onProcessOverrideDimensions) {
disposables.add(p.onProcessOverrideDimensions(e => this._proxy.$sendOverrideDimensions(id, e)));
}
this._terminalProcesses[id] = p;
this._terminalProcesses.set(id, p);
const awaitingStart = this._extensionTerminalAwaitingStart[id];
if (awaitingStart && p instanceof ExtHostPseudoterminal) {
......@@ -532,12 +539,12 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
}
public $acceptProcessInput(id: number, data: string): void {
this._terminalProcesses[id]?.input(data);
this._terminalProcesses.get(id)?.input(data);
}
public $acceptProcessResize(id: number, cols: number, rows: number): void {
try {
this._terminalProcesses[id]?.resize(cols, rows);
this._terminalProcesses.get(id)?.resize(cols, rows);
} catch (error) {
// We tried to write to a closed pipe / channel.
if (error.code !== 'EPIPE' && error.code !== 'ERR_IPC_CHANNEL_CLOSED') {
......@@ -547,15 +554,15 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
}
public $acceptProcessShutdown(id: number, immediate: boolean): void {
this._terminalProcesses[id]?.shutdown(immediate);
this._terminalProcesses.get(id)?.shutdown(immediate);
}
public $acceptProcessRequestInitialCwd(id: number): void {
this._terminalProcesses[id]?.getInitialCwd().then(initialCwd => this._proxy.$sendProcessInitialCwd(id, initialCwd));
this._terminalProcesses.get(id)?.getInitialCwd().then(initialCwd => this._proxy.$sendProcessInitialCwd(id, initialCwd));
}
public $acceptProcessRequestCwd(id: number): void {
this._terminalProcesses[id]?.getCwd().then(cwd => this._proxy.$sendProcessCwd(id, cwd));
this._terminalProcesses.get(id)?.getCwd().then(cwd => this._proxy.$sendProcessCwd(id, cwd));
}
public $acceptProcessRequestLatency(id: number): number {
......@@ -648,7 +655,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ
this._bufferer.stopBuffering(id);
// Remove process reference
delete this._terminalProcesses[id];
this._terminalProcesses.delete(id);
delete this._extensionTerminalAwaitingStart[id];
// Clean up process disposables
......
......@@ -21,6 +21,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IExtHostRpcService, ExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { IURITransformerService, URITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
import { IExtHostExtensionService, IHostUtils } from 'vs/workbench/api/common/extHostExtensionService';
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
export interface IExitFn {
(code?: number): any;
......@@ -61,6 +62,9 @@ export class ExtensionHostMain {
// todo@joh
// ugly self - inject
const terminalService = instaService.invokeFunction(accessor => accessor.get(IExtHostTerminalService));
this._disposables.add(terminalService);
const logService = instaService.invokeFunction(accessor => accessor.get(ILogService));
this._disposables.add(logService);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册