diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index d3a7aeeed3812..403b26e084d71 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -234,7 +234,7 @@ export interface IPtyService { getTerminalLayoutInfo(args: IGetTerminalLayoutInfoArgs): Promise; reduceConnectionGraceTime(): Promise; requestDetachInstance(workspaceId: string, instanceId: number): Promise; - acceptDetachedInstance(requestId: number, process: number): Promise; + acceptDetachInstanceReply(requestId: number, persistentProcessId?: number): Promise; } export interface IRequestResolveVariablesEvent { diff --git a/src/vs/platform/terminal/node/ptyHostService.ts b/src/vs/platform/terminal/node/ptyHostService.ts index cf40e5d8738a1..e9cc652400cc3 100644 --- a/src/vs/platform/terminal/node/ptyHostService.ts +++ b/src/vs/platform/terminal/node/ptyHostService.ts @@ -252,8 +252,8 @@ export class PtyHostService extends Disposable implements IPtyService { return this._proxy.requestDetachInstance(workspaceId, instanceId); } - async acceptDetachedInstance(requestId: number, persistentProcessId: number): Promise { - return this._proxy.acceptDetachedInstance(requestId, persistentProcessId); + async acceptDetachInstanceReply(requestId: number, persistentProcessId: number): Promise { + return this._proxy.acceptDetachInstanceReply(requestId, persistentProcessId); } async restartPtyHost(): Promise { diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 3206624f62afa..312332847d0f2 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -5,9 +5,9 @@ import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IProcessEnvironment, isWindows, OperatingSystem, OS } from 'vs/base/common/platform'; -import { IPtyService, IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalsLayoutInfo, IRawTerminalInstanceLayoutInfo, ITerminalTabLayoutInfoById, ITerminalInstanceLayoutInfoById, TerminalShellType, IProcessReadyEvent, TitleEventSource, TerminalIcon, IReconnectConstants } from 'vs/platform/terminal/common/terminal'; +import { IPtyService, IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalsLayoutInfo, IRawTerminalInstanceLayoutInfo, ITerminalTabLayoutInfoById, ITerminalInstanceLayoutInfoById, TerminalShellType, IProcessReadyEvent, TitleEventSource, TerminalIcon, IReconnectConstants, IRequestResolveVariablesEvent } from 'vs/platform/terminal/common/terminal'; import { AutoOpenBarrier, Queue, RunOnceScheduler } from 'vs/base/common/async'; -import { Emitter } from 'vs/base/common/event'; +import { Emitter, Event } from 'vs/base/common/event'; import { TerminalRecorder } from 'vs/platform/terminal/common/terminalRecorder'; import { TerminalProcess } from 'vs/platform/terminal/node/terminalProcess'; import { ISetTerminalLayoutInfoArgs, ITerminalTabLayoutInfoDto, IProcessDetails, IGetTerminalLayoutInfoArgs, IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminalProcess'; @@ -72,12 +72,17 @@ export class PtyService extends Disposable implements IPtyService { this._detachInstanceRequestStore = this._register(new RequestStore(undefined, this._logService)); this._detachInstanceRequestStore.onCreateRequest(this._onDidRequestDetach.fire, this._onDidRequestDetach); } + onPtyHostExit?: Event | undefined; + onPtyHostStart?: Event | undefined; + onPtyHostUnresponsive?: Event | undefined; + onPtyHostResponsive?: Event | undefined; + onPtyHostRequestResolveVariables?: Event | undefined; async requestDetachInstance(workspaceId: string, instanceId: number): Promise { return this._detachInstanceRequestStore.createRequest({ workspaceId, instanceId }); } - async acceptDetachedInstance(requestId: number, persistentProcessId: number): Promise { + async acceptDetachInstanceReply(requestId: number, persistentProcessId: number): Promise { let processDetails: IProcessDetails | undefined = undefined; const pty = this._ptys.get(persistentProcessId); if (pty) { diff --git a/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts b/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts index 48f4cd79c5a55..018f2ad7a3c63 100644 --- a/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts @@ -162,13 +162,16 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal return this._remoteTerminalChannel.requestDetachInstance(workspaceId, instanceId); } - async acceptDetachedInstance(requestId: number, persistentProcessId: number): Promise { + async acceptDetachInstanceReply(requestId: number, persistentProcessId?: number): Promise { if (!this._remoteTerminalChannel) { throw new Error(`Cannot accept detached instance when there is no remote!`); + } else if (!persistentProcessId) { + this._logService.warn('Cannot attach to feature terminals, custom pty terminals, or those without a persistentProcessId'); + return; } - return this._remoteTerminalChannel.acceptDetachedInstance(requestId, persistentProcessId); - } + return this._remoteTerminalChannel.acceptDetachInstanceReply(requestId, persistentProcessId); + } async createProcess(shellLaunchConfig: IShellLaunchConfig, configuration: ICompleteTerminalConfiguration, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, shouldPersist: boolean, configHelper: ITerminalConfigHelper): Promise { if (!this._remoteTerminalChannel) { diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index c1c4c71f919f3..69e6de34df9a2 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -338,8 +338,8 @@ export interface ITerminalInstance { readonly instanceId: number; /** * A unique URI for this terminal instance with the following encoding: - * path: Title - * fragment: workspace ID / instance ID + * path: // + * fragment: Title */ readonly resource: URI; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index d6fbc0e723dad..0b0779e110e5a 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -267,7 +267,10 @@ export class TerminalService implements ITerminalService { const persistentProcessId = instanceToDetach?.persistentProcessId; if (persistentProcessId && !instanceToDetach.shellLaunchConfig.isFeatureTerminal && !instanceToDetach.shellLaunchConfig.customPtyImplementation) { await instanceToDetach.detachFromProcess(); - await this._primaryOffProcessTerminalService?.acceptDetachedInstance(e.requestId, persistentProcessId); + await this._primaryOffProcessTerminalService?.acceptDetachInstanceReply(e.requestId, persistentProcessId); + } else { + // will get rejected without a persistentProcessId to attach to + await this._primaryOffProcessTerminalService?.acceptDetachInstanceReply(e.requestId, undefined); } } }); diff --git a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts index 62e8fa6ac35ff..429bcadc2b175 100644 --- a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts +++ b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts @@ -204,8 +204,8 @@ export class RemoteTerminalChannelClient { requestDetachInstance(workspaceId: string, instanceId: number): Promise { return this._channel.call('$requestDetachInstance', [workspaceId, instanceId]); } - acceptDetachedInstance(requestId: number, persistentProcessId: number): Promise { - return this._channel.call('$acceptDetachedInstance', [requestId, persistentProcessId]); + acceptDetachInstanceReply(requestId: number, persistentProcessId: number): Promise { + return this._channel.call('$acceptDetachInstanceReply', [requestId, persistentProcessId]); } attachToProcess(id: number): Promise { return this._channel.call('$attachToProcess', [id]); diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index de15e73476c3a..be768b975a969 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -96,7 +96,7 @@ export interface IOffProcessTerminalService { getTerminalLayoutInfo(): Promise; reduceConnectionGraceTime(): Promise; requestDetachInstance(workspaceId: string, instanceId: number): Promise; - acceptDetachedInstance(requestId: number, persistentProcessId: number): Promise; + acceptDetachInstanceReply(requestId: number, persistentProcessId?: number): Promise; } export const ILocalTerminalService = createDecorator('localTerminalService'); diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts index 8b76e021826a6..ae219c309f211 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts @@ -130,8 +130,12 @@ export class LocalTerminalService extends Disposable implements ILocalTerminalSe return this._localPtyService.requestDetachInstance(workspaceId, instanceId); } - async acceptDetachedInstance(requestId: number, persistentProcessId: number): Promise { - await this._localPtyService.acceptDetachedInstance(requestId, persistentProcessId); + async acceptDetachInstanceReply(requestId: number, persistentProcessId?: number): Promise { + if (!persistentProcessId) { + this._logService.warn('Cannot attach to feature terminals, custom pty terminals, or those without a persistentProcessId'); + return; + } + return this._localPtyService.acceptDetachInstanceReply(requestId, persistentProcessId); } async updateTitle(id: number, title: string, titleSource: TitleEventSource): Promise { diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index f104fd830526e..1e868cc2956a8 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -1684,7 +1684,7 @@ export class TestLocalTerminalService implements ILocalTerminalService { updateTitle(id: number, title: string): Promise { throw new Error('Method not implemented.'); } updateIcon(id: number, icon: URI | { light: URI; dark: URI } | { id: string, color?: { id: string } }, color?: string): Promise { throw new Error('Method not implemented.'); } requestDetachInstance(workspaceId: string, instanceId: number): Promise { throw new Error('Method not implemented.'); } - acceptDetachedInstance(requestId: number, persistentProcessId: number): Promise { throw new Error('Method not implemented.'); } + acceptDetachInstanceReply(requestId: number, persistentProcessId: number): Promise { throw new Error('Method not implemented.'); } } class TestTerminalChildProcess implements ITerminalChildProcess {