55
66import { Emitter , Event } from 'vs/base/common/event' ;
77import { Disposable , toDisposable } from 'vs/base/common/lifecycle' ;
8- import { IProcessEnvironment , OperatingSystem , isWindows } from 'vs/base/common/platform' ;
8+ import { IProcessEnvironment , OS , OperatingSystem , isWindows } from 'vs/base/common/platform' ;
99import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc' ;
1010import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
11- import { ILogService , ILoggerService } from 'vs/platform/log/common/log' ;
11+ import { ILogService , ILoggerService , LogLevel } from 'vs/platform/log/common/log' ;
1212import { RemoteLoggerChannelClient } from 'vs/platform/log/common/logIpc' ;
1313import { getResolvedShellEnv } from 'vs/platform/shell/node/shellEnv' ;
1414import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/capabilities/capabilities' ;
@@ -19,6 +19,7 @@ import { IGetTerminalLayoutInfoArgs, IProcessDetails, ISetTerminalLayoutInfoArgs
1919import { IPtyHostConnection , IPtyHostStarter } from 'vs/platform/terminal/node/ptyHost' ;
2020import { detectAvailableProfiles } from 'vs/platform/terminal/node/terminalProfiles' ;
2121import * as performance from 'vs/base/common/performance' ;
22+ import { getSystemShell } from 'vs/base/node/shell' ;
2223
2324enum Constants {
2425 MaxRestarts = 5
@@ -43,6 +44,13 @@ export class PtyHostService extends Disposable implements IPtyService {
4344 this . _ensurePtyHost ( ) ;
4445 return this . __proxy ! ;
4546 }
47+ /**
48+ * Get the proxy if it exists, otherwise undefined. This is used when calls are not needed to be
49+ * passed through to the pty host if it has not yet been spawned.
50+ */
51+ private get _optionalProxy ( ) : IPtyService | undefined {
52+ return this . __proxy ;
53+ }
4654
4755 private _ensurePtyHost ( ) {
4856 if ( ! this . __connection ) {
@@ -102,12 +110,9 @@ export class PtyHostService extends Disposable implements IPtyService {
102110 this . _resolveVariablesRequestStore = this . _register ( new RequestStore ( undefined , this . _logService ) ) ;
103111 this . _resolveVariablesRequestStore . onCreateRequest ( this . _onPtyHostRequestResolveVariables . fire , this . _onPtyHostRequestResolveVariables ) ;
104112
105- // Force the pty host to start as the first window is starting if the starter has that
106- // capability
107- if ( this . _ptyHostStarter . onBeforeWindowConnection ) {
108- Event . once ( this . _ptyHostStarter . onBeforeWindowConnection ) ( ( ) => this . _ensurePtyHost ( ) ) ;
109- } else {
110- this . _ensurePtyHost ( ) ;
113+ // Start the pty host when a window requests a connection, if the starter has that capability.
114+ if ( this . _ptyHostStarter . onRequestConnection ) {
115+ Event . once ( this . _ptyHostStarter . onRequestConnection ) ( ( ) => this . _ensurePtyHost ( ) ) ;
111116 }
112117
113118 this . _ptyHostStarter . onWillShutdown ?.( ( ) => this . _wasQuitRequested = true ) ;
@@ -118,7 +123,7 @@ export class PtyHostService extends Disposable implements IPtyService {
118123 }
119124
120125 private async _refreshIgnoreProcessNames ( ) : Promise < void > {
121- return this . _proxy . refreshIgnoreProcessNames ?.( this . _ignoreProcessNames ) ;
126+ return this . _optionalProxy ? .refreshIgnoreProcessNames ?.( this . _ignoreProcessNames ) ;
122127 }
123128
124129 private async _resolveShellEnv ( ) : Promise < typeof process . env > {
@@ -139,6 +144,11 @@ export class PtyHostService extends Disposable implements IPtyService {
139144 const connection = this . _ptyHostStarter . start ( ) ;
140145 const client = connection . client ;
141146
147+ // Log a full stack trace which will tell the exact reason the pty host is starting up
148+ if ( this . _logService . getLevel ( ) === LogLevel . Trace ) {
149+ this . _logService . trace ( 'PtyHostService#_startPtyHost' , new Error ( ) . stack ?. replace ( / ^ E r r o r / , '' ) ) ;
150+ }
151+
142152 // Setup heartbeat service and trigger a heartbeat immediately to reset the timeouts
143153 const heartbeatService = ProxyChannel . toService < IHeartbeatService > ( client . getChannel ( TerminalIpcChannels . Heartbeat ) ) ;
144154 heartbeatService . onBeat ( ( ) => this . _handleHeartbeat ( ) ) ;
@@ -224,13 +234,10 @@ export class PtyHostService extends Disposable implements IPtyService {
224234 return this . _proxy . listProcesses ( ) ;
225235 }
226236 async getPerformanceMarks ( ) : Promise < performance . PerformanceMark [ ] > {
227- if ( ! this . __proxy ) {
228- return [ ] ;
229- }
230- return this . _proxy . getPerformanceMarks ( ) ;
237+ return this . _optionalProxy ?. getPerformanceMarks ( ) ?? [ ] ;
231238 }
232- reduceConnectionGraceTime ( ) : Promise < void > {
233- return this . _proxy . reduceConnectionGraceTime ( ) ;
239+ async reduceConnectionGraceTime ( ) : Promise < void > {
240+ return this . _optionalProxy ? .reduceConnectionGraceTime ( ) ;
234241 }
235242 start ( id : number ) : Promise < ITerminalLaunchError | { injectedArgs : string [ ] } | undefined > {
236243 return this . _proxy . start ( id ) ;
@@ -280,7 +287,7 @@ export class PtyHostService extends Disposable implements IPtyService {
280287 }
281288
282289 getDefaultSystemShell ( osOverride ?: OperatingSystem ) : Promise < string > {
283- return this . _proxy . getDefaultSystemShell ( osOverride ) ;
290+ return this . _optionalProxy ? .getDefaultSystemShell ( osOverride ) ?? getSystemShell ( osOverride ?? OS , process . env ) ;
284291 }
285292 async getProfiles ( workspaceId : string , profiles : unknown , defaultProfile : unknown , includeDetectedProfiles : boolean = false ) : Promise < ITerminalProfile [ ] > {
286293 const shellEnv = await this . _resolveShellEnv ( ) ;
0 commit comments