Persistent terminal id -> Persistent process id

Part of #117978
This commit is contained in:
Daniel Imms 2021-03-02 11:15:28 -08:00
parent 647773d7e6
commit e994e5ab49
10 changed files with 62 additions and 62 deletions

View file

@ -17,7 +17,7 @@ export type ITerminalInstanceLayoutInfo = IRawTerminalInstanceLayoutInfo<IPtyHos
export interface IRawTerminalTabLayoutInfo<T> {
isActive: boolean;
activePersistentTerminalId: number | undefined;
activePersistentProcessId: number | undefined;
terminals: IRawTerminalInstanceLayoutInfo<T>[];
}
@ -199,7 +199,7 @@ export interface IShellLaunchConfig {
/**
* This is a terminal that attaches to an already running terminal.
*/
attachPersistentTerminal?: { id: number; pid: number; title: string; cwd: string; };
attachPersistentProcess?: { id: number; pid: number; title: string; cwd: string; };
/**
* Whether the terminal process environment should be exactly as provided in

View file

@ -69,7 +69,7 @@ export class PtyService extends Disposable implements IPtyService {
workspaceId: string,
workspaceName: string
): Promise<number> {
if (shellLaunchConfig.attachPersistentTerminal) {
if (shellLaunchConfig.attachPersistentProcess) {
throw new Error('Attempt to create a process when attach object was provided');
}
const id = ++this._lastPtyId;
@ -82,24 +82,24 @@ export class PtyService extends Disposable implements IPtyService {
if (process.onProcessResolvedShellLaunchConfig) {
process.onProcessResolvedShellLaunchConfig(event => this._onProcessResolvedShellLaunchConfig.fire({ id, event }));
}
const persistentTerminalProcess = new PersistentTerminalProcess(id, process, workspaceId, workspaceName, shouldPersist, cols, rows, this._logService);
const persistentProcess = new PersistentTerminalProcess(id, process, workspaceId, workspaceName, shouldPersist, cols, rows, this._logService);
process.onProcessExit(() => {
persistentTerminalProcess.dispose();
persistentProcess.dispose();
this._ptys.delete(id);
});
persistentTerminalProcess.onProcessReplay(event => this._onProcessReplay.fire({ id, event }));
persistentTerminalProcess.onProcessReady(event => this._onProcessReady.fire({ id, event }));
persistentTerminalProcess.onProcessTitleChanged(event => this._onProcessTitleChanged.fire({ id, event }));
this._ptys.set(id, persistentTerminalProcess);
persistentProcess.onProcessReplay(event => this._onProcessReplay.fire({ id, event }));
persistentProcess.onProcessReady(event => this._onProcessReady.fire({ id, event }));
persistentProcess.onProcessTitleChanged(event => this._onProcessTitleChanged.fire({ id, event }));
this._ptys.set(id, persistentProcess);
return id;
}
async attachToProcess(id: number): Promise<void> {
try {
this._throwIfNoPty(id).attach();
this._logService.trace(`Persistent terminal reconnection "${id}"`);
this._logService.trace(`Persistent process reconnection "${id}"`);
} catch (e) {
this._logService.trace(`Persistent terminal reconnection "${id}" failed`, e.message);
this._logService.trace(`Persistent process reconnection "${id}" failed`, e.message);
}
}
@ -153,15 +153,15 @@ export class PtyService extends Disposable implements IPtyService {
const filtered = expandedTerminals.filter(term => term.terminal !== null) as IRawTerminalInstanceLayoutInfo<IPtyHostDescriptionDto>[];
return {
isActive: tab.isActive,
activePersistentTerminalId: tab.activePersistentTerminalId,
activePersistentProcessId: tab.activePersistentProcessId,
terminals: filtered
};
}
private async _expandTerminalInstance(t: ITerminalInstanceLayoutInfoById): Promise<IRawTerminalInstanceLayoutInfo<IPtyHostDescriptionDto | null>> {
try {
const persistentTerminalProcess = this._throwIfNoPty(t.terminal);
const termDto = persistentTerminalProcess && await this._terminalToDto(t.terminal, persistentTerminalProcess);
const persistentProcess = this._throwIfNoPty(t.terminal);
const termDto = persistentProcess && await this._terminalToDto(t.terminal, persistentProcess);
return {
terminal: termDto ?? null,
relativeSize: t.relativeSize
@ -176,14 +176,14 @@ export class PtyService extends Disposable implements IPtyService {
}
}
private async _terminalToDto(id: number, persistentTerminalProcess: PersistentTerminalProcess): Promise<IPtyHostDescriptionDto> {
const [cwd, isOrphan] = await Promise.all([persistentTerminalProcess.getCwd(), persistentTerminalProcess.isOrphaned()]);
private async _terminalToDto(id: number, persistentProcess: PersistentTerminalProcess): Promise<IPtyHostDescriptionDto> {
const [cwd, isOrphan] = await Promise.all([persistentProcess.getCwd(), persistentProcess.isOrphaned()]);
return {
id,
title: persistentTerminalProcess.title,
pid: persistentTerminalProcess.pid,
workspaceId: persistentTerminalProcess.workspaceId,
workspaceName: persistentTerminalProcess.workspaceName,
title: persistentProcess.title,
pid: persistentProcess.pid,
workspaceId: persistentProcess.workspaceId,
workspaceName: persistentProcess.workspaceName,
cwd,
isOrphan
};
@ -233,7 +233,7 @@ export class PersistentTerminalProcess extends Disposable {
get title(): string { return this._terminalProcess.currentTitle; }
constructor(
private _persistentTerminalId: number,
private _persistentProcessId: number,
private readonly _terminalProcess: TerminalProcess,
public readonly workspaceId: string,
public readonly workspaceName: string,
@ -246,11 +246,11 @@ export class PersistentTerminalProcess extends Disposable {
this._orphanQuestionBarrier = null;
this._orphanQuestionReplyTime = 0;
this._disconnectRunner1 = this._register(new RunOnceScheduler(() => {
this._logService.info(`Persistent terminal "${this._persistentTerminalId}": The reconnection grace time of ${printTime(LocalReconnectConstants.ReconnectionGraceTime)} has expired, so the process (pid=${this._pid}) will be shutdown.`);
this._logService.info(`Persistent process "${this._persistentProcessId}": The reconnection grace time of ${printTime(LocalReconnectConstants.ReconnectionGraceTime)} has expired, shutting down pid "${this._pid}"`);
this.shutdown(true);
}, LocalReconnectConstants.ReconnectionGraceTime));
this._disconnectRunner2 = this._register(new RunOnceScheduler(() => {
this._logService.info(`Persistent terminal "${this._persistentTerminalId}": The short reconnection grace time of ${printTime(LocalReconnectConstants.ReconnectionShortGraceTime)} has expired, so the process (pid=${this._pid}) will be shutdown.`);
this._logService.info(`Persistent process "${this._persistentProcessId}": The short reconnection grace time of ${printTime(LocalReconnectConstants.ReconnectionShortGraceTime)} has expired, shutting down pid ${this._pid}`);
this.shutdown(true);
}, LocalReconnectConstants.ReconnectionShortGraceTime));
@ -271,10 +271,10 @@ export class PersistentTerminalProcess extends Disposable {
this._register(this._terminalProcess.onProcessTitleChanged(e => this._onProcessTitleChanged.fire(e)));
// Buffer data events to reduce the amount of messages going to the renderer
// this._register(this._bufferer.startBuffering(this._persistentTerminalId, this._terminalProcess.onProcessData));
// this._register(this._bufferer.startBuffering(this._persistentProcessId, this._terminalProcess.onProcessData));
this._register(this._terminalProcess.onProcessData(e => this._recorder.recordData(e)));
this._register(this._terminalProcess.onProcessExit(exitCode => {
// this._bufferer.stopBuffering(this._persistentTerminalId);
// this._bufferer.stopBuffering(this._persistentProcessId);
}));
}
@ -344,7 +344,7 @@ export class PersistentTerminalProcess extends Disposable {
dataLength += e.data.length;
}
this._logService.info(`Persistent terminal "${this._persistentTerminalId}": Replaying ${dataLength} chars and ${ev.events.length} size events`);
this._logService.info(`Persistent process "${this._persistentProcessId}": Replaying ${dataLength} chars and ${ev.events.length} size events`);
this._onProcessReplay.fire(ev);
this._terminalProcess.clearUnacknowledgedChars();
}

View file

@ -103,8 +103,8 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP
public get onProcessResolvedShellLaunchConfig(): Event<IShellLaunchConfig> { return this._onProcessResolvedShellLaunchConfig.event; }
private _startBarrier: Barrier;
private _persistentTerminalId: number;
public get id(): number { return this._persistentTerminalId; }
private _persistentProcessId: number;
public get id(): number { return this._persistentProcessId; }
private _inReplay = false;
@ -124,7 +124,7 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP
) {
super();
this._startBarrier = new Barrier();
this._persistentTerminalId = 0;
this._persistentProcessId = 0;
if (this._isPreconnectionTerminal) {
// Add a loading title only if this terminal is
@ -141,7 +141,7 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP
throw new Error('Could not fetch remote environment');
}
if (!this._shellLaunchConfig.attachPersistentTerminal) {
if (!this._shellLaunchConfig.attachPersistentProcess) {
const isWorkspaceShellAllowed = this._configHelper.checkWorkspaceShellPermissions(env.os);
const shellLaunchConfigDto: IShellLaunchConfigDto = {
@ -163,23 +163,23 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP
isWorkspaceShellAllowed,
);
this._persistentTerminalId = result.terminalId;
this._persistentProcessId = result.terminalId;
this.setupTerminalEventListener();
this._onProcessResolvedShellLaunchConfig.fire(reviveIShellLaunchConfig(result.resolvedShellLaunchConfig));
const startResult = await this._remoteTerminalChannel.startTerminalProcess(this._persistentTerminalId);
const startResult = await this._remoteTerminalChannel.startTerminalProcess(this._persistentProcessId);
if (typeof startResult !== 'undefined') {
// An error occurred
return startResult;
}
} else {
this._persistentTerminalId = this._shellLaunchConfig.attachPersistentTerminal.id;
this._onProcessReady.fire({ pid: this._shellLaunchConfig.attachPersistentTerminal.pid, cwd: this._shellLaunchConfig.attachPersistentTerminal.cwd });
this._persistentProcessId = this._shellLaunchConfig.attachPersistentProcess.id;
this._onProcessReady.fire({ pid: this._shellLaunchConfig.attachPersistentProcess.pid, cwd: this._shellLaunchConfig.attachPersistentProcess.cwd });
this.setupTerminalEventListener();
setTimeout(() => {
this._onProcessTitleChanged.fire(this._shellLaunchConfig.attachPersistentTerminal!.title);
this._onProcessTitleChanged.fire(this._shellLaunchConfig.attachPersistentProcess!.title);
}, 0);
}
@ -189,7 +189,7 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP
public shutdown(immediate: boolean): void {
this._startBarrier.wait().then(_ => {
this._remoteTerminalChannel.shutdownTerminalProcess(this._persistentTerminalId, immediate);
this._remoteTerminalChannel.shutdownTerminalProcess(this._persistentProcessId, immediate);
});
}
@ -199,12 +199,12 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP
}
this._startBarrier.wait().then(_ => {
this._remoteTerminalChannel.sendInputToTerminalProcess(this._persistentTerminalId, data);
this._remoteTerminalChannel.sendInputToTerminalProcess(this._persistentProcessId, data);
});
}
private setupTerminalEventListener(): void {
this._register(this._remoteTerminalChannel.onTerminalProcessEvent(this._persistentTerminalId)(event => {
this._register(this._remoteTerminalChannel.onTerminalProcessEvent(this._persistentProcessId)(event => {
switch (event.type) {
case 'ready':
return this._onProcessReady.fire({ pid: event.pid, cwd: event.cwd });
@ -237,7 +237,7 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP
case 'execCommand':
return this._execCommand(event);
case 'orphan?': {
this._remoteTerminalChannel.orphanQuestionReply(this._persistentTerminalId);
this._remoteTerminalChannel.orphanQuestionReply(this._persistentProcessId);
return;
}
}
@ -250,7 +250,7 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP
}
this._startBarrier.wait().then(_ => {
this._remoteTerminalChannel.resizeTerminalProcess(this._persistentTerminalId, cols, rows);
this._remoteTerminalChannel.resizeTerminalProcess(this._persistentProcessId, cols, rows);
});
}
@ -261,18 +261,18 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP
}
this._startBarrier.wait().then(_ => {
this._remoteTerminalChannel.sendCharCountToTerminalProcess(this._persistentTerminalId, charCount);
this._remoteTerminalChannel.sendCharCountToTerminalProcess(this._persistentProcessId, charCount);
});
}
public async getInitialCwd(): Promise<string> {
await this._startBarrier.wait();
return this._remoteTerminalChannel.getTerminalInitialCwd(this._persistentTerminalId);
return this._remoteTerminalChannel.getTerminalInitialCwd(this._persistentProcessId);
}
public async getCwd(): Promise<string> {
await this._startBarrier.wait();
return this._remoteTerminalChannel.getTerminalCwd(this._persistentTerminalId);
return this._remoteTerminalChannel.getTerminalCwd(this._persistentProcessId);
}
/**
@ -287,9 +287,9 @@ export class RemoteTerminalProcess extends Disposable implements ITerminalChildP
const commandArgs = event.commandArgs.map(arg => revive(arg));
try {
const result = await this._commandService.executeCommand(event.commandId, ...commandArgs);
this._remoteTerminalChannel.sendCommandResultToTerminalProcess(this._persistentTerminalId, reqId, false, result);
this._remoteTerminalChannel.sendCommandResultToTerminalProcess(this._persistentProcessId, reqId, false, result);
} catch (err) {
this._remoteTerminalChannel.sendCommandResultToTerminalProcess(this._persistentTerminalId, reqId, true, err);
this._remoteTerminalChannel.sendCommandResultToTerminalProcess(this._persistentProcessId, reqId, true, err);
}
}
}

View file

@ -275,10 +275,10 @@ export interface ITerminalInstance {
processId: number | undefined;
/**
* The id of a persistent terminal. Defined if this is a terminal created
* by the RemoteTerminalService or LocalPtyService.
* The id of a persistent process. This is defined if this is a terminal created by a pty host
* that supports reconnection.
*/
readonly persistentTerminalId: number | undefined;
readonly persistentProcessId: number | undefined;
/**
* Whether the process should be persisted across reloads.

View file

@ -687,7 +687,7 @@ export function registerTerminalActions() {
});
const selected = await quickInputService.pick<IRemoteTerminalPick>(items, { canPickMany: false });
if (selected) {
const instance = terminalService.createTerminal({ attachPersistentTerminal: selected.term });
const instance = terminalService.createTerminal({ attachPersistentProcess: selected.term });
terminalService.setActiveInstance(instance);
terminalService.showPanel(true);
}

View file

@ -373,7 +373,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
return TerminalInstance._lastKnownCanvasDimensions;
}
public get persistentTerminalId(): number | undefined { return this._processManager.persistentTerminalId; }
public get persistentProcessId(): number | undefined { return this._processManager.persistentProcessId; }
public get shouldPersist(): boolean { return this._processManager.shouldPersist; }
private async _getXtermConstructor(): Promise<typeof XTermTerminal> {
@ -1591,7 +1591,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
// Recreate the process if the terminal has not yet been interacted with and it's not a
// special terminal (eg. task, extension terminal)
if (info.requiresAction && !this._processManager.hasWrittenData && !this._shellLaunchConfig.isFeatureTerminal && !this._shellLaunchConfig.isExtensionTerminal && !this._shellLaunchConfig.attachPersistentTerminal) {
if (info.requiresAction && !this._processManager.hasWrittenData && !this._shellLaunchConfig.isFeatureTerminal && !this._shellLaunchConfig.isExtensionTerminal && !this._shellLaunchConfig.attachPersistentProcess) {
this.relaunch();
return;
}

View file

@ -89,7 +89,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
public get onEnvironmentVariableInfoChanged(): Event<IEnvironmentVariableInfo> { return this._onEnvironmentVariableInfoChange.event; }
public get environmentVariableInfo(): IEnvironmentVariableInfo | undefined { return this._environmentVariableInfo; }
public get persistentTerminalId(): number | undefined { return this._process?.id; }
public get persistentProcessId(): number | undefined { return this._process?.id; }
public get shouldPersist(): boolean { return this._process ? this._process.shouldPersist : false; }
public get hasWrittenData(): boolean {
@ -190,12 +190,12 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
} else {
// Flow control is not needed for ptys hosted in the same process (ie. the electron
// renderer).
if (shellLaunchConfig.attachPersistentTerminal) {
const result = await this._terminalInstanceService.attachToProcess(shellLaunchConfig.attachPersistentTerminal.id);
if (shellLaunchConfig.attachPersistentProcess) {
const result = await this._terminalInstanceService.attachToProcess(shellLaunchConfig.attachPersistentProcess.id);
if (result) {
this._process = result;
} else {
this._logService.trace(`Attach to process failed for terminal ${shellLaunchConfig.attachPersistentTerminal}`);
this._logService.trace(`Attach to process failed for terminal ${shellLaunchConfig.attachPersistentProcess}`);
return undefined;
}
} else {

View file

@ -200,18 +200,18 @@ export class TerminalService implements ITerminalService {
terminalLayouts.forEach((terminalLayout) => {
if (!terminalInstance) {
// create tab and terminal
terminalInstance = this.createTerminal({ attachPersistentTerminal: terminalLayout.terminal! });
terminalInstance = this.createTerminal({ attachPersistentProcess: terminalLayout.terminal! });
tab = this._getTabForInstance(terminalInstance);
if (tabLayout.isActive) {
activeTab = tab;
}
} else {
// add split terminals to this tab
this.splitInstance(terminalInstance, { attachPersistentTerminal: terminalLayout.terminal! });
this.splitInstance(terminalInstance, { attachPersistentProcess: terminalLayout.terminal! });
}
});
const activeInstance = this.terminalInstances.find(t => {
return t.shellLaunchConfig.attachPersistentTerminal?.id === tabLayout.activePersistentTerminalId;
return t.shellLaunchConfig.attachPersistentProcess?.id === tabLayout.activePersistentProcessId;
});
if (activeInstance) {
this.setActiveInstance(activeInstance);

View file

@ -299,15 +299,15 @@ export class TerminalTab extends Disposable implements ITerminalTab {
public getLayoutInfo(isActive: boolean): ITerminalTabLayoutInfoById {
const isHorizontal = this.splitPaneContainer?.orientation === Orientation.HORIZONTAL;
const instances = this.terminalInstances.filter(instance => typeof instance.persistentTerminalId === 'number' && instance.shouldPersist);
const instances = this.terminalInstances.filter(instance => typeof instance.persistentProcessId === 'number' && instance.shouldPersist);
const totalSize = instances.map(instance => isHorizontal ? instance.cols : instance.rows).reduce((totalValue, currentValue) => totalValue + currentValue, 0);
return {
isActive: isActive,
activePersistentTerminalId: this.activeInstance ? this.activeInstance.persistentTerminalId : undefined,
activePersistentProcessId: this.activeInstance ? this.activeInstance.persistentProcessId : undefined,
terminals: instances.map(t => {
return {
relativeSize: isHorizontal ? t.cols / totalSize : t.rows / totalSize,
terminal: t.persistentTerminalId || 0
terminal: t.persistentProcessId || 0
};
})
};

View file

@ -244,7 +244,7 @@ export interface ITerminalProcessManager extends IDisposable {
readonly os: OperatingSystem | undefined;
readonly userHome: string | undefined;
readonly environmentVariableInfo: IEnvironmentVariableInfo | undefined;
readonly persistentTerminalId: number | undefined;
readonly persistentProcessId: number | undefined;
readonly shouldPersist: boolean;
/** Whether the process has had data written to it yet. */
readonly hasWrittenData: boolean;