From 71c15eac23c7cf2e32b3ed8222c6ac4d35c614ba Mon Sep 17 00:00:00 2001 From: Stephen Sigwart Date: Sat, 11 Jun 2022 20:57:05 -0400 Subject: [PATCH 1/8] Fix terminals in editor area not reloading - Closes #140429 - This isn't perfect because it just reopens then without setting the original location, but at least it reloads them. --- src/vs/platform/terminal/common/terminal.ts | 5 +++ .../terminal/common/terminalProcess.ts | 3 +- src/vs/platform/terminal/node/ptyService.ts | 26 ++++++++++++-- .../terminal/browser/terminalService.ts | 35 +++++++++++++++++-- .../terminal/common/remoteTerminalChannel.ts | 3 +- .../electron-sandbox/localTerminalBackend.ts | 3 +- 6 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 91b3244bd3fe6..a368b53f6c72c 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -133,6 +133,9 @@ export interface IRawTerminalInstanceLayoutInfo { relativeSize: number; terminal: T; } +export interface IRawTerminalEditorInstanceLayoutInfo { + terminal: T; +} export type ITerminalInstanceLayoutInfoById = IRawTerminalInstanceLayoutInfo; export type ITerminalInstanceLayoutInfo = IRawTerminalInstanceLayoutInfo; @@ -143,9 +146,11 @@ export interface IRawTerminalTabLayoutInfo { } export type ITerminalTabLayoutInfoById = IRawTerminalTabLayoutInfo; +export type ITerminalEditorInstanceLayoutInfoById = IRawTerminalEditorInstanceLayoutInfo; export interface IRawTerminalsLayoutInfo { tabs: IRawTerminalTabLayoutInfo[]; + editorTerminals: IRawTerminalEditorInstanceLayoutInfo[]; } export interface IPtyHostAttachTarget { diff --git a/src/vs/platform/terminal/common/terminalProcess.ts b/src/vs/platform/terminal/common/terminalProcess.ts index dea87c461a104..d949d919061a1 100644 --- a/src/vs/platform/terminal/common/terminalProcess.ts +++ b/src/vs/platform/terminal/common/terminalProcess.ts @@ -5,7 +5,7 @@ import { UriComponents } from 'vs/base/common/uri'; import { ISerializableEnvironmentVariableCollection } from 'vs/platform/terminal/common/environmentVariable'; -import { IFixedTerminalDimensions, IRawTerminalTabLayoutInfo, ITerminalEnvironment, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource } from 'vs/platform/terminal/common/terminal'; +import { IFixedTerminalDimensions, IRawTerminalTabLayoutInfo, ITerminalEnvironment, ITerminalTabLayoutInfoById, ITerminalEditorInstanceLayoutInfoById, TerminalIcon, TitleEventSource } from 'vs/platform/terminal/common/terminal'; export interface ISingleTerminalConfiguration { userValue: T | undefined; @@ -41,6 +41,7 @@ export interface IWorkspaceFolderData { export interface ISetTerminalLayoutInfoArgs { workspaceId: string; tabs: ITerminalTabLayoutInfoById[]; + editorTerminals: ITerminalEditorInstanceLayoutInfoById[]; } export interface IGetTerminalLayoutInfoArgs { diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 397fee9a49308..250c44a283863 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { getSystemShell } from 'vs/base/node/shell'; import { ILogService } from 'vs/platform/log/common/log'; import { RequestStore } from 'vs/platform/terminal/common/requestStore'; -import { IProcessDataEvent, IProcessReadyEvent, IPtyService, IRawTerminalInstanceLayoutInfo, IReconnectConstants, IRequestResolveVariablesEvent, IShellLaunchConfig, ITerminalInstanceLayoutInfoById, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalTabLayoutInfoById, TerminalIcon, IProcessProperty, TitleEventSource, ProcessPropertyType, IProcessPropertyMap, IFixedTerminalDimensions, IPersistentTerminalProcessLaunchConfig, ICrossVersionSerializedTerminalState, ISerializedTerminalState, ITerminalProcessOptions } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IPtyService, IRawTerminalInstanceLayoutInfo, IReconnectConstants, IRequestResolveVariablesEvent, IShellLaunchConfig, ITerminalInstanceLayoutInfoById, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalTabLayoutInfoById, TerminalIcon, IProcessProperty, TitleEventSource, ProcessPropertyType, IProcessPropertyMap, IFixedTerminalDimensions, IPersistentTerminalProcessLaunchConfig, ICrossVersionSerializedTerminalState, ISerializedTerminalState, ITerminalProcessOptions, ITerminalEditorInstanceLayoutInfoById, IRawTerminalEditorInstanceLayoutInfo } from 'vs/platform/terminal/common/terminal'; import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering'; import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnvironment'; import { Terminal as XtermTerminal } from 'xterm-headless'; @@ -343,8 +343,12 @@ export class PtyService extends Disposable implements IPtyService { if (layout) { const expandedTabs = await Promise.all(layout.tabs.map(async tab => this._expandTerminalTab(tab))); const tabs = expandedTabs.filter(t => t.terminals.length > 0); + const expandedEditors = await Promise.all(layout.editorTerminals.map(async editorTerminal => this._expandTerminalEditorInstance(editorTerminal))); this._logService.trace('ptyService#returnLayoutInfo', tabs); - return { tabs }; + return { + tabs, + editorTerminals: expandedEditors + }; } return undefined; } @@ -379,6 +383,24 @@ export class PtyService extends Disposable implements IPtyService { } } + private async _expandTerminalEditorInstance(t: ITerminalEditorInstanceLayoutInfoById): Promise> { + try { + const revivedPtyId = this._revivedPtyIdMap.get(t.terminal)?.newId; + const persistentProcessId = revivedPtyId ?? t.terminal; + const persistentProcess = this._throwIfNoPty(persistentProcessId); + const processDetails = persistentProcess && await this._buildProcessDetails(t.terminal, persistentProcess, revivedPtyId !== undefined); + return { + terminal: { ...processDetails, id: persistentProcessId } ?? null + }; + } catch (e) { + this._logService.trace(`Couldn't get layout info, a terminal was probably disconnected`, e.message); + // this will be filtered out and not reconnected + return { + terminal: null + }; + } + } + private async _buildProcessDetails(id: number, persistentProcess: PersistentTerminalProcess, wasRevived: boolean = false): Promise { // If the process was just revived, don't do the orphan check as it will // take some time diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 62d52e82cc942..4bb83addb4284 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -403,8 +403,18 @@ export class TerminalService implements ITerminalService { return; } const layoutInfo = await localBackend.getTerminalLayoutInfo(); - if (layoutInfo && layoutInfo.tabs.length > 0) { - await this._recreateTerminalGroups(layoutInfo); + if (layoutInfo) { + if (layoutInfo.tabs.length > 0) { + await this._recreateTerminalGroups(layoutInfo); + } + if (layoutInfo.editorTerminals && layoutInfo.editorTerminals.length > 0) { + for (const editorTerminal of layoutInfo.editorTerminals) { + await this.createTerminal({ + config: { attachPersistentProcess: editorTerminal.terminal! }, + location: TerminalLocation.Editor + }); + } + } } // now that terminals have been restored, // attach listeners to update local state when terminals are changed @@ -642,7 +652,26 @@ export class TerminalService implements ITerminalService { return; } const tabs = this._terminalGroupService.groups.map(g => g.getLayoutInfo(g === this._terminalGroupService.activeGroup)); - const state: ITerminalsLayoutInfoById = { tabs }; + + // Save terminals in editors too + const seenPersistentProcessIds: number[] = []; + for (const t of tabs) { + for (const term of t.terminals) { + seenPersistentProcessIds.push(term.terminal); + } + } + const otherInstances = this.instances.filter(instance => typeof instance.persistentProcessId === 'number' && instance.shouldPersist && seenPersistentProcessIds.indexOf(instance.persistentProcessId) === -1); + const editorTerminals = otherInstances.map((instance) => { + instance. + return { + terminal: instance.persistentProcessId || 0 + }; + }); + + const state: ITerminalsLayoutInfoById = { + tabs, + editorTerminals + }; this._primaryBackend?.setTerminalLayoutInfo(state); } diff --git a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts index e8c7da68932bc..a41a5f89716cb 100644 --- a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts +++ b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts @@ -266,7 +266,8 @@ export class RemoteTerminalChannelClient implements IPtyHostController { const workspace = this._workspaceContextService.getWorkspace(); const args: ISetTerminalLayoutInfoArgs = { workspaceId: workspace.id, - tabs: layout ? layout.tabs : [] + tabs: layout ? layout.tabs : [], + editorTerminals: layout ? layout.editorTerminals : [] }; return this._channel.call('$setTerminalLayoutInfo', args); } diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts index b2f01c3e853c2..e423da8a59ff6 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts @@ -199,7 +199,8 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke async setTerminalLayoutInfo(layoutInfo?: ITerminalsLayoutInfoById): Promise { const args: ISetTerminalLayoutInfoArgs = { workspaceId: this._getWorkspaceId(), - tabs: layoutInfo ? layoutInfo.tabs : [] + tabs: layoutInfo ? layoutInfo.tabs : [], + editorTerminals: layoutInfo ? layoutInfo.editorTerminals : [] }; await this._localPtyService.setTerminalLayoutInfo(args); // Store in the storage service as well to be used when reviving processes as normally this From f33aeb876f2acd410693ccd241b667ce4173fd09 Mon Sep 17 00:00:00 2001 From: Stephen Sigwart Date: Sat, 11 Jun 2022 21:07:33 -0400 Subject: [PATCH 2/8] Fix accidental line of code --- src/vs/workbench/contrib/terminal/browser/terminalService.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 4bb83addb4284..e8b200aa2f119 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -662,8 +662,7 @@ export class TerminalService implements ITerminalService { } const otherInstances = this.instances.filter(instance => typeof instance.persistentProcessId === 'number' && instance.shouldPersist && seenPersistentProcessIds.indexOf(instance.persistentProcessId) === -1); const editorTerminals = otherInstances.map((instance) => { - instance. - return { + return { terminal: instance.persistentProcessId || 0 }; }); From f1008c80bbcc9a170f0686c12eaa8da9c4d91504 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 14 Jun 2022 21:54:33 -0700 Subject: [PATCH 3/8] fix imports --- src/vs/platform/terminal/common/terminalProcess.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/terminal/common/terminalProcess.ts b/src/vs/platform/terminal/common/terminalProcess.ts index 09ae38589cfb4..980c345a6bd12 100644 --- a/src/vs/platform/terminal/common/terminalProcess.ts +++ b/src/vs/platform/terminal/common/terminalProcess.ts @@ -5,9 +5,7 @@ import { UriComponents } from 'vs/base/common/uri'; import { ISerializableEnvironmentVariableCollection } from 'vs/platform/terminal/common/environmentVariable'; -import { IFixedTerminalDimensions, IRawTerminalTabLayoutInfo, ITerminalEnvironment, ITerminalTabLayoutInfoById, ITerminalEditorInstanceLayoutInfoById, TerminalIcon, TitleEventSource } from 'vs/platform/terminal/common/terminal'; -import { ISerializableEnvironmentVariableCollection, ISerializableEnvironmentVariableCollections } from 'vs/platform/terminal/common/environmentVariable'; -import { IFixedTerminalDimensions, IRawTerminalTabLayoutInfo, ITerminalEnvironment, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource } from 'vs/platform/terminal/common/terminal'; +import { IFixedTerminalDimensions, IRawTerminalTabLayoutInfo, ITerminalEditorInstanceLayoutInfoById, ITerminalEnvironment, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource } from 'vs/platform/terminal/common/terminal'; export interface ISingleTerminalConfiguration { userValue: T | undefined; @@ -62,7 +60,7 @@ export interface IProcessDetails { icon: TerminalIcon | undefined; color: string | undefined; fixedDimensions: IFixedTerminalDimensions | undefined; - environmentVariableCollections: ISerializableEnvironmentVariableCollections | undefined; + environmentVariableCollections: ISerializableEnvironmentVariableCollection | undefined; } export type ITerminalTabLayoutInfoDto = IRawTerminalTabLayoutInfo; From a084f63f4d3e5477efbcd8851008e8d996a45681 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Wed, 15 Jun 2022 10:17:53 -0700 Subject: [PATCH 4/8] fix issues --- src/vs/platform/terminal/common/terminalProcess.ts | 4 ++-- src/vs/workbench/contrib/terminal/browser/terminalService.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/terminal/common/terminalProcess.ts b/src/vs/platform/terminal/common/terminalProcess.ts index 980c345a6bd12..fa7e3252db1cf 100644 --- a/src/vs/platform/terminal/common/terminalProcess.ts +++ b/src/vs/platform/terminal/common/terminalProcess.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { UriComponents } from 'vs/base/common/uri'; -import { ISerializableEnvironmentVariableCollection } from 'vs/platform/terminal/common/environmentVariable'; +import { ISerializableEnvironmentVariableCollection, ISerializableEnvironmentVariableCollections } from 'vs/platform/terminal/common/environmentVariable'; import { IFixedTerminalDimensions, IRawTerminalTabLayoutInfo, ITerminalEditorInstanceLayoutInfoById, ITerminalEnvironment, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource } from 'vs/platform/terminal/common/terminal'; export interface ISingleTerminalConfiguration { @@ -60,7 +60,7 @@ export interface IProcessDetails { icon: TerminalIcon | undefined; color: string | undefined; fixedDimensions: IFixedTerminalDimensions | undefined; - environmentVariableCollections: ISerializableEnvironmentVariableCollection | undefined; + environmentVariableCollections: ISerializableEnvironmentVariableCollections | undefined; } export type ITerminalTabLayoutInfoDto = IRawTerminalTabLayoutInfo; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index f9ba263232c5f..02072ae283cf3 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -21,6 +21,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ILogService } from 'vs/platform/log/common/log'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ICreateContributedTerminalProfileOptions, IShellLaunchConfig, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalLocation, TerminalLocationString, TitleEventSource } from 'vs/platform/terminal/common/terminal'; +import { formatMessageForTerminal } from 'vs/platform/terminal/common/terminalStrings'; import { iconForeground } from 'vs/platform/theme/common/colorRegistry'; import { getIconRegistry } from 'vs/platform/theme/common/iconRegistry'; import { ColorScheme } from 'vs/platform/theme/common/theme'; @@ -38,7 +39,6 @@ import { getInstanceFromResource, getTerminalUri, parseTerminalUri } from 'vs/wo import { TerminalViewPane } from 'vs/workbench/contrib/terminal/browser/terminalView'; import { IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalBackend, ITerminalConfigHelper, ITerminalProcessExtHostProxy, ITerminalProfileService, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; -import { formatMessageForTerminal } from 'vs/platform/terminal/common/terminalStrings'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; From bc7344685d7213a16a1a0c43d8287d824692c4ae Mon Sep 17 00:00:00 2001 From: meganrogge Date: Fri, 17 Jun 2022 08:51:28 -0700 Subject: [PATCH 5/8] check length of editor terminals --- .../terminal/browser/terminalEditorService.ts | 2 ++ .../contrib/terminal/browser/terminalService.ts | 16 ++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts b/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts index aec68ee5d91a5..5a501adebd2d0 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts @@ -93,6 +93,7 @@ export class TerminalEditorService extends Disposable implements ITerminalEditor // Remove the terminal from the managed instances when the editor closes. This fires when // dragging and dropping to another editor or closing the editor via cmd/ctrl+w. this._register(this._editorService.onDidCloseEditor(e => { + console.log('closed editor'); const instance = e.editor instanceof TerminalEditorInput ? e.editor.terminalInstance : undefined; if (instance) { const instanceIndex = this.instances.findIndex(e => e === instance); @@ -100,6 +101,7 @@ export class TerminalEditorService extends Disposable implements ITerminalEditor this.instances.splice(instanceIndex, 1); } } + console.log(this.instances); })); this._register(this._editorService.onDidActiveEditorChange(() => { const instance = this._editorService.activeEditor instanceof TerminalEditorInput ? this._editorService.activeEditor : undefined; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 02072ae283cf3..4d1220d4375bb 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -407,12 +407,16 @@ export class TerminalService implements ITerminalService { if (layoutInfo.tabs.length > 0) { await this._recreateTerminalGroups(layoutInfo); } - if (layoutInfo.editorTerminals && layoutInfo.editorTerminals.length > 0) { - for (const editorTerminal of layoutInfo.editorTerminals) { - await this.createTerminal({ - config: { attachPersistentProcess: editorTerminal.terminal! }, - location: TerminalLocation.Editor - }); + if (this._terminalEditorService.instances.length === 0) { + // only do this for restart because editor terminals are already restored + // on reload + if (layoutInfo.editorTerminals && layoutInfo.editorTerminals.length > 0) { + for (const editorTerminal of layoutInfo.editorTerminals) { + await this.createTerminal({ + config: { attachPersistentProcess: editorTerminal.terminal! }, + location: TerminalLocation.Editor + }); + } } } } From 7aa326e2d7a802cb8622842309e10196ce228b53 Mon Sep 17 00:00:00 2001 From: Stephen Sigwart Date: Sat, 18 Jun 2022 15:26:59 -0400 Subject: [PATCH 6/8] Get info from terminal editor - The issue is `_onWillShutdown` is called before `TerminalInputSerializer` serializes, so I added `shutdownPersistentProcessId`. - When restoring the editor, it was using the wrong ID, so I added `getRevivedPtyNewId`. --- src/vs/platform/terminal/common/terminal.ts | 8 +--- .../terminal/common/terminalProcess.ts | 3 +- .../platform/terminal/node/ptyHostService.ts | 4 ++ src/vs/platform/terminal/node/ptyService.ts | 34 +++++---------- src/vs/server/node/remoteTerminalChannel.ts | 1 + .../terminal/browser/remoteTerminalBackend.ts | 17 ++++++++ .../contrib/terminal/browser/terminal.ts | 5 +++ .../terminal/browser/terminalEditorService.ts | 3 +- .../terminal/browser/terminalInstance.ts | 8 +++- .../browser/terminalProcessManager.ts | 2 +- .../terminal/browser/terminalService.ts | 41 ++++--------------- .../terminal/common/remoteTerminalChannel.ts | 7 +++- .../contrib/terminal/common/terminal.ts | 1 + .../electron-sandbox/localTerminalBackend.ts | 16 +++++++- 14 files changed, 78 insertions(+), 72 deletions(-) diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index fefc6dfe9365e..4bd9644b0b153 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -134,9 +134,6 @@ export interface IRawTerminalInstanceLayoutInfo { relativeSize: number; terminal: T; } -export interface IRawTerminalEditorInstanceLayoutInfo { - terminal: T; -} export type ITerminalInstanceLayoutInfoById = IRawTerminalInstanceLayoutInfo; export type ITerminalInstanceLayoutInfo = IRawTerminalInstanceLayoutInfo; @@ -147,11 +144,9 @@ export interface IRawTerminalTabLayoutInfo { } export type ITerminalTabLayoutInfoById = IRawTerminalTabLayoutInfo; -export type ITerminalEditorInstanceLayoutInfoById = IRawTerminalEditorInstanceLayoutInfo; export interface IRawTerminalsLayoutInfo { tabs: IRawTerminalTabLayoutInfo[]; - editorTerminals: IRawTerminalEditorInstanceLayoutInfo[]; } export interface IPtyHostAttachTarget { @@ -317,6 +312,7 @@ export interface IPtyService extends IPtyHostController { getProfiles?(workspaceId: string, profiles: unknown, defaultProfile: unknown, includeDetectedProfiles?: boolean): Promise; getEnvironment(): Promise; getWslPath(original: string): Promise; + getRevivedPtyNewId(id: number): Promise; setTerminalLayoutInfo(args: ISetTerminalLayoutInfoArgs): Promise; getTerminalLayoutInfo(args: IGetTerminalLayoutInfoArgs): Promise; reduceConnectionGraceTime(): Promise; @@ -463,7 +459,7 @@ export interface IShellLaunchConfig { /** * This is a terminal that attaches to an already running terminal. */ - attachPersistentProcess?: { id: number; pid: number; title: string; titleSource: TitleEventSource; cwd: string; icon?: TerminalIcon; color?: string; hasChildProcesses?: boolean; fixedDimensions?: IFixedTerminalDimensions; environmentVariableCollections?: ISerializableEnvironmentVariableCollections }; + attachPersistentProcess?: { id: number; findRevivedId?: boolean; pid: number; title: string; titleSource: TitleEventSource; cwd: string; icon?: TerminalIcon; color?: string; hasChildProcesses?: boolean; fixedDimensions?: IFixedTerminalDimensions; environmentVariableCollections?: ISerializableEnvironmentVariableCollections }; /** * Whether the terminal process environment should be exactly as provided in diff --git a/src/vs/platform/terminal/common/terminalProcess.ts b/src/vs/platform/terminal/common/terminalProcess.ts index fa7e3252db1cf..f89a48394a525 100644 --- a/src/vs/platform/terminal/common/terminalProcess.ts +++ b/src/vs/platform/terminal/common/terminalProcess.ts @@ -5,7 +5,7 @@ import { UriComponents } from 'vs/base/common/uri'; import { ISerializableEnvironmentVariableCollection, ISerializableEnvironmentVariableCollections } from 'vs/platform/terminal/common/environmentVariable'; -import { IFixedTerminalDimensions, IRawTerminalTabLayoutInfo, ITerminalEditorInstanceLayoutInfoById, ITerminalEnvironment, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource } from 'vs/platform/terminal/common/terminal'; +import { IFixedTerminalDimensions, IRawTerminalTabLayoutInfo, ITerminalEnvironment, ITerminalTabLayoutInfoById, TerminalIcon, TitleEventSource } from 'vs/platform/terminal/common/terminal'; export interface ISingleTerminalConfiguration { userValue: T | undefined; @@ -41,7 +41,6 @@ export interface IWorkspaceFolderData { export interface ISetTerminalLayoutInfoArgs { workspaceId: string; tabs: ITerminalTabLayoutInfoById[]; - editorTerminals: ITerminalEditorInstanceLayoutInfoById[]; } export interface IGetTerminalLayoutInfoArgs { diff --git a/src/vs/platform/terminal/node/ptyHostService.ts b/src/vs/platform/terminal/node/ptyHostService.ts index b7679d75f9025..2f4371ddcefd5 100644 --- a/src/vs/platform/terminal/node/ptyHostService.ts +++ b/src/vs/platform/terminal/node/ptyHostService.ts @@ -296,6 +296,10 @@ export class PtyHostService extends Disposable implements IPtyService { return this._proxy.getWslPath(original); } + getRevivedPtyNewId(id: number): Promise { + return this._proxy.getRevivedPtyNewId(id); + } + setTerminalLayoutInfo(args: ISetTerminalLayoutInfoArgs): Promise { return this._proxy.setTerminalLayoutInfo(args); } diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 093414825517e..659a2f7f500f6 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { getSystemShell } from 'vs/base/node/shell'; import { ILogService } from 'vs/platform/log/common/log'; import { RequestStore } from 'vs/platform/terminal/common/requestStore'; -import { IProcessDataEvent, IProcessReadyEvent, IPtyService, IRawTerminalInstanceLayoutInfo, IReconnectConstants, IRequestResolveVariablesEvent, IShellLaunchConfig, ITerminalInstanceLayoutInfoById, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalTabLayoutInfoById, TerminalIcon, IProcessProperty, TitleEventSource, ProcessPropertyType, IProcessPropertyMap, IFixedTerminalDimensions, IPersistentTerminalProcessLaunchConfig, ICrossVersionSerializedTerminalState, ISerializedTerminalState, ITerminalProcessOptions, ITerminalEditorInstanceLayoutInfoById, IRawTerminalEditorInstanceLayoutInfo } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IPtyService, IRawTerminalInstanceLayoutInfo, IReconnectConstants, IRequestResolveVariablesEvent, IShellLaunchConfig, ITerminalInstanceLayoutInfoById, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalTabLayoutInfoById, TerminalIcon, IProcessProperty, TitleEventSource, ProcessPropertyType, IProcessPropertyMap, IFixedTerminalDimensions, IPersistentTerminalProcessLaunchConfig, ICrossVersionSerializedTerminalState, ISerializedTerminalState, ITerminalProcessOptions } from 'vs/platform/terminal/common/terminal'; import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering'; import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnvironment'; import { Terminal as XtermTerminal } from 'xterm-headless'; @@ -334,21 +334,27 @@ export class PtyService extends Disposable implements IPtyService { }); } + async getRevivedPtyNewId(id: number): Promise { + try { + return this._revivedPtyIdMap.get(id)?.newId; + } catch (e) { + this._logService.trace(`Couldn't find terminal ID ${id}`, e.message); + } + return undefined; + } + async setTerminalLayoutInfo(args: ISetTerminalLayoutInfoArgs): Promise { this._workspaceLayoutInfos.set(args.workspaceId, args); } async getTerminalLayoutInfo(args: IGetTerminalLayoutInfoArgs): Promise { const layout = this._workspaceLayoutInfos.get(args.workspaceId); - this._logService.trace('ptyService#getLayoutInfo', args); if (layout) { const expandedTabs = await Promise.all(layout.tabs.map(async tab => this._expandTerminalTab(tab))); const tabs = expandedTabs.filter(t => t.terminals.length > 0); - const expandedEditors = await Promise.all(layout.editorTerminals.map(async editorTerminal => this._expandTerminalEditorInstance(editorTerminal))); this._logService.trace('ptyService#returnLayoutInfo', tabs); return { - tabs, - editorTerminals: expandedEditors + tabs }; } return undefined; @@ -384,24 +390,6 @@ export class PtyService extends Disposable implements IPtyService { } } - private async _expandTerminalEditorInstance(t: ITerminalEditorInstanceLayoutInfoById): Promise> { - try { - const revivedPtyId = this._revivedPtyIdMap.get(t.terminal)?.newId; - const persistentProcessId = revivedPtyId ?? t.terminal; - const persistentProcess = this._throwIfNoPty(persistentProcessId); - const processDetails = persistentProcess && await this._buildProcessDetails(t.terminal, persistentProcess, revivedPtyId !== undefined); - return { - terminal: { ...processDetails, id: persistentProcessId } ?? null - }; - } catch (e) { - this._logService.trace(`Couldn't get layout info, a terminal was probably disconnected`, e.message); - // this will be filtered out and not reconnected - return { - terminal: null - }; - } - } - private async _buildProcessDetails(id: number, persistentProcess: PersistentTerminalProcess, wasRevived: boolean = false): Promise { // If the process was just revived, don't do the orphan check as it will // take some time diff --git a/src/vs/server/node/remoteTerminalChannel.ts b/src/vs/server/node/remoteTerminalChannel.ts index 5c14bf3006cf9..96241c74e8cab 100644 --- a/src/vs/server/node/remoteTerminalChannel.ts +++ b/src/vs/server/node/remoteTerminalChannel.ts @@ -138,6 +138,7 @@ export class RemoteTerminalChannel extends Disposable implements IServerChannel< case '$setTerminalLayoutInfo': return this._ptyService.setTerminalLayoutInfo(args); case '$serializeTerminalState': return this._ptyService.serializeTerminalState.apply(this._ptyService, args); case '$reviveTerminalProcesses': return this._ptyService.reviveTerminalProcesses.apply(this._ptyService, args); + case '$getRevivedPtyNewId': return this._ptyService.getRevivedPtyNewId.apply(this._ptyService, args); case '$setUnicodeVersion': return this._ptyService.setUnicodeVersion.apply(this._ptyService, args); case '$reduceConnectionGraceTime': return this._reduceConnectionGraceTime(); case '$updateIcon': return this._ptyService.updateIcon.apply(this._ptyService, args); diff --git a/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts b/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts index dbbcea77cf990..6b304681efd95 100644 --- a/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts @@ -239,6 +239,23 @@ class RemoteTerminalBackend extends BaseTerminalBackend implements ITerminalBack return undefined; } + async attachToRevivedProcess(id: number): Promise { + if (!this._remoteTerminalChannel) { + throw new Error(`Cannot create remote terminal when there is no remote!`); + } + + try { + const newId = await this._remoteTerminalChannel.getRevivedPtyNewId(id); + if (newId === undefined) { + return undefined; + } + return await this.attachToProcess(newId); + } catch (e) { + this._logService.trace(`Couldn't attach to process ${e.message}`); + } + return undefined; + } + async listProcesses(): Promise { const terms = this._remoteTerminalChannel ? await this._remoteTerminalChannel.listProcesses() : []; return terms.map(termDto => { diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index d11e3359e8ad0..ecff6314eec74 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -470,6 +470,11 @@ export interface ITerminalInstance { */ readonly persistentProcessId: number | undefined; + /** + * The id of a persistent process during the shutdown process + */ + shutdownPersistentProcessId: number | undefined; + /** * Whether the process should be persisted across reloads. */ diff --git a/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts b/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts index 5a501adebd2d0..5ed91cd6c1297 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts @@ -281,7 +281,8 @@ export class TerminalEditorService extends Disposable implements ITerminalEditor const inputKey = resource.path; if ('pid' in deserializedInput) { - const instance = this._terminalInstanceService.createInstance({ attachPersistentProcess: deserializedInput }, TerminalLocation.Editor); + const newDeserializedInput = { ...deserializedInput, findRevivedId: true }; + const instance = this._terminalInstanceService.createInstance({ attachPersistentProcess: newDeserializedInput }, TerminalLocation.Editor); instance.target = TerminalLocation.Editor; const input = this._instantiationService.createInstance(TerminalEditorInput, resource, instance); this._registerInstance(inputKey, input, instance); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 7f9589e2ca357..119ef061d0a61 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -150,6 +150,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private readonly _processManager: ITerminalProcessManager; private readonly _resource: URI; + private _shutdownPersistentProcessId: number | undefined; // Enables disposal of the xterm onKey // event when the CwdDetection capability @@ -654,8 +655,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return TerminalInstance._lastKnownCanvasDimensions; } - get persistentProcessId(): number | undefined { return this._processManager.persistentProcessId; } - get shouldPersist(): boolean { return this._processManager.shouldPersist && !this.shellLaunchConfig.isTransient; } + set shutdownPersistentProcessId(shutdownPersistentProcessId: number | undefined) { + this._shutdownPersistentProcessId = shutdownPersistentProcessId; + } + get persistentProcessId(): number | undefined { return this._processManager.persistentProcessId ?? this._shutdownPersistentProcessId; } + get shouldPersist(): boolean { return (this._processManager.shouldPersist || this._shutdownPersistentProcessId !== undefined) && !this.shellLaunchConfig.isTransient; } /** * Create xterm.js instance and attach data listeners. diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index bba89cdbceee1..db29d77039185 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -290,7 +290,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce } } else { if (shellLaunchConfig.attachPersistentProcess) { - const result = await backend.attachToProcess(shellLaunchConfig.attachPersistentProcess.id); + const result = shellLaunchConfig.attachPersistentProcess.findRevivedId ? await backend.attachToRevivedProcess(shellLaunchConfig.attachPersistentProcess.id) : await backend.attachToProcess(shellLaunchConfig.attachPersistentProcess.id); if (result) { newProcess = result; } else { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 4d1220d4375bb..69ec76c20d0c6 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -403,22 +403,8 @@ export class TerminalService implements ITerminalService { return; } const layoutInfo = await localBackend.getTerminalLayoutInfo(); - if (layoutInfo) { - if (layoutInfo.tabs.length > 0) { - await this._recreateTerminalGroups(layoutInfo); - } - if (this._terminalEditorService.instances.length === 0) { - // only do this for restart because editor terminals are already restored - // on reload - if (layoutInfo.editorTerminals && layoutInfo.editorTerminals.length > 0) { - for (const editorTerminal of layoutInfo.editorTerminals) { - await this.createTerminal({ - config: { attachPersistentProcess: editorTerminal.terminal! }, - location: TerminalLocation.Editor - }); - } - } - } + if (layoutInfo && layoutInfo.tabs.length > 0) { + await this._recreateTerminalGroups(layoutInfo); } // now that terminals have been restored, // attach listeners to update local state when terminals are changed @@ -634,8 +620,13 @@ export class TerminalService implements ITerminalService { return; } + // Force dispose of all terminal instances + const shouldPersistTerminalsForEvent = this._shouldReviveProcesses(e.reason); for (const instance of this.instances) { + if (shouldPersistTerminalsForEvent) { + instance.shutdownPersistentProcessId = instance.persistentProcessId; + } instance.dispose(); } @@ -659,24 +650,8 @@ export class TerminalService implements ITerminalService { return; } const tabs = this._terminalGroupService.groups.map(g => g.getLayoutInfo(g === this._terminalGroupService.activeGroup)); - - // Save terminals in editors too - const seenPersistentProcessIds: number[] = []; - for (const t of tabs) { - for (const term of t.terminals) { - seenPersistentProcessIds.push(term.terminal); - } - } - const otherInstances = this.instances.filter(instance => typeof instance.persistentProcessId === 'number' && instance.shouldPersist && seenPersistentProcessIds.indexOf(instance.persistentProcessId) === -1); - const editorTerminals = otherInstances.map((instance) => { - return { - terminal: instance.persistentProcessId || 0 - }; - }); - const state: ITerminalsLayoutInfoById = { - tabs, - editorTerminals + tabs }; this._primaryBackend?.setTerminalLayoutInfo(state); } diff --git a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts index a41a5f89716cb..1b62d1e9cb331 100644 --- a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts +++ b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts @@ -266,8 +266,7 @@ export class RemoteTerminalChannelClient implements IPtyHostController { const workspace = this._workspaceContextService.getWorkspace(); const args: ISetTerminalLayoutInfoArgs = { workspaceId: workspace.id, - tabs: layout ? layout.tabs : [], - editorTerminals: layout ? layout.editorTerminals : [] + tabs: layout ? layout.tabs : [] }; return this._channel.call('$setTerminalLayoutInfo', args); } @@ -300,6 +299,10 @@ export class RemoteTerminalChannelClient implements IPtyHostController { return this._channel.call('$reviveTerminalProcesses', [state, dateTimeFormatLocate]); } + getRevivedPtyNewId(id: number): Promise { + return this._channel.call('$getRevivedPtyNewId', [id]); + } + serializeTerminalState(ids: number[]): Promise { return this._channel.call('$serializeTerminalState', [ids]); } diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 1d3a1aa85dbae..04b98030a4195 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -116,6 +116,7 @@ export interface ITerminalBackend { onDidRequestDetach: Event<{ requestId: number; workspaceId: string; instanceId: number }>; attachToProcess(id: number): Promise; + attachToRevivedProcess(id: number): Promise; listProcesses(): Promise; getDefaultSystemShell(osOverride?: OperatingSystem): Promise; getProfiles(profiles: unknown, defaultProfile: unknown, includeDetectedProfiles?: boolean): Promise; diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts index e423da8a59ff6..8b9802f0abc54 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts @@ -168,6 +168,19 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke return undefined; } + async attachToRevivedProcess(id: number): Promise { + try { + const newId = await this._localPtyService.getRevivedPtyNewId(id); + if (newId === undefined) { + return undefined; + } + return await this.attachToProcess(newId); + } catch (e) { + this._logService.trace(`Couldn't attach to process ${e.message}`); + } + return undefined; + } + async listProcesses(): Promise { return this._localPtyService.listProcesses(); } @@ -199,8 +212,7 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke async setTerminalLayoutInfo(layoutInfo?: ITerminalsLayoutInfoById): Promise { const args: ISetTerminalLayoutInfoArgs = { workspaceId: this._getWorkspaceId(), - tabs: layoutInfo ? layoutInfo.tabs : [], - editorTerminals: layoutInfo ? layoutInfo.editorTerminals : [] + tabs: layoutInfo ? layoutInfo.tabs : [] }; await this._localPtyService.setTerminalLayoutInfo(args); // Store in the storage service as well to be used when reviving processes as normally this From 1f37af91f0533162174ce784e023af03b6c0d7ed Mon Sep 17 00:00:00 2001 From: Stephen Sigwart Date: Sat, 18 Jun 2022 15:30:19 -0400 Subject: [PATCH 7/8] Self review cleanup --- src/vs/platform/terminal/node/ptyService.ts | 5 ++--- .../contrib/terminal/browser/terminalEditorService.ts | 2 -- src/vs/workbench/contrib/terminal/browser/terminalService.ts | 4 +--- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 659a2f7f500f6..02494098900b2 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -349,13 +349,12 @@ export class PtyService extends Disposable implements IPtyService { async getTerminalLayoutInfo(args: IGetTerminalLayoutInfoArgs): Promise { const layout = this._workspaceLayoutInfos.get(args.workspaceId); + this._logService.trace('ptyService#getLayoutInfo', args); if (layout) { const expandedTabs = await Promise.all(layout.tabs.map(async tab => this._expandTerminalTab(tab))); const tabs = expandedTabs.filter(t => t.terminals.length > 0); this._logService.trace('ptyService#returnLayoutInfo', tabs); - return { - tabs - }; + return { tabs }; } return undefined; } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts b/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts index 5ed91cd6c1297..74b83274dca13 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalEditorService.ts @@ -93,7 +93,6 @@ export class TerminalEditorService extends Disposable implements ITerminalEditor // Remove the terminal from the managed instances when the editor closes. This fires when // dragging and dropping to another editor or closing the editor via cmd/ctrl+w. this._register(this._editorService.onDidCloseEditor(e => { - console.log('closed editor'); const instance = e.editor instanceof TerminalEditorInput ? e.editor.terminalInstance : undefined; if (instance) { const instanceIndex = this.instances.findIndex(e => e === instance); @@ -101,7 +100,6 @@ export class TerminalEditorService extends Disposable implements ITerminalEditor this.instances.splice(instanceIndex, 1); } } - console.log(this.instances); })); this._register(this._editorService.onDidActiveEditorChange(() => { const instance = this._editorService.activeEditor instanceof TerminalEditorInput ? this._editorService.activeEditor : undefined; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 69ec76c20d0c6..11e980b5f71d1 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -650,9 +650,7 @@ export class TerminalService implements ITerminalService { return; } const tabs = this._terminalGroupService.groups.map(g => g.getLayoutInfo(g === this._terminalGroupService.activeGroup)); - const state: ITerminalsLayoutInfoById = { - tabs - }; + const state: ITerminalsLayoutInfoById = { tabs }; this._primaryBackend?.setTerminalLayoutInfo(state); } From 9dcdfa421e249c14cceb2c8bcd8e9f407e738457 Mon Sep 17 00:00:00 2001 From: Stephen Sigwart Date: Mon, 20 Jun 2022 20:41:14 -0400 Subject: [PATCH 8/8] Use same ID for reload to reconnect --- .../contrib/terminal/browser/remoteTerminalBackend.ts | 5 +---- .../terminal/electron-sandbox/localTerminalBackend.ts | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts b/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts index 6b304681efd95..35454bcae4e12 100644 --- a/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts @@ -245,10 +245,7 @@ class RemoteTerminalBackend extends BaseTerminalBackend implements ITerminalBack } try { - const newId = await this._remoteTerminalChannel.getRevivedPtyNewId(id); - if (newId === undefined) { - return undefined; - } + const newId = await this._remoteTerminalChannel.getRevivedPtyNewId(id) ?? id; return await this.attachToProcess(newId); } catch (e) { this._logService.trace(`Couldn't attach to process ${e.message}`); diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts index 8b9802f0abc54..d61acd4c4a431 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts @@ -170,10 +170,7 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke async attachToRevivedProcess(id: number): Promise { try { - const newId = await this._localPtyService.getRevivedPtyNewId(id); - if (newId === undefined) { - return undefined; - } + const newId = await this._localPtyService.getRevivedPtyNewId(id) ?? id; return await this.attachToProcess(newId); } catch (e) { this._logService.trace(`Couldn't attach to process ${e.message}`);