Change:
Type: <bBug</bSeems to be a timing issue. The following steps sometimes reproduce it for me, but success may depend on the performance of your workstation (mine is Windows) and which other extensions are enabled by default. the statusbar-sample folder in VS Code a Terminal in that folder and run to Debug view, choose the configuration and run it. This launches with Extension Host window appears, look on the right of the status bar. If the repro was successful it will look like this: ! If this doesn't happen, try the next steps: debugging and launch the configuration instead. This launches normally and probably won't trigger the problem: ! Command Palette of the EH window, run . With luck this will cause the problem to happen (see first screenshot). The extension activates , so immediately on startup. The first attempt to get happens from its method. If the problem shows, click the status bar panel to get the value again. This time it should succeed. VS Code version: Code - Insiders 1.72.0-insider (, 2022-09-12T05:16:16.290Z) OS version: Windows_NT x64 10.0. Modes: Sandboxed: Yes <!-- generated by issue reporter --
Looks like you should be using extension host init data for this, not a dynamic value that changes along the way
wouldn't that mean blocking the extension host launch on the pty host and its profile detection round trip? I believe this has always been like this and the value is dynamic depending on settings/environment.
yes - either block or make it clear that the value changes, e.g we need an event to signal changes. I am not familiar with how this works, does the shell-value change during a single session?
Changing the default shell (via settings or UI) will change the value. Let's track adding this API in this issue:
Would an early-activating extension expect to receive this event when the value of changes from its apparent initial value of emptystring to whatever shell is the initial default? As I understand it, for some modes of VS Code operation will always be emptystring. So my extension would probably have to do other tests to check for those, otherwise it could wait forever for an event telling it that the initial shell is now known.
yes may be undefined, for example in Not sure what you're doing exactly but you could listen on and enable the functionality at that point, or after some timeout? Our class in core would be handy to implement that In the meantime I recommend you poll for the initial value and give up after some time, you may also want to re-check the value at a later point as well as it can change.
Submitted a PR for this. Do you think that works?
Leaving this open for future finalization
from the activate method of the extension we call and use its method to run commands. When composing the command string we check to discover what shell we'll be interacting with. We're working around the problem by retrying the call a few times. The proposed API should allow a different strategy in future, but we might just stay with what we're doing.
I think my job would have been easier if the returned by had a property that told me what shell it was using. Currently it has a property from which I can only discover the shell if had specified explicitly.
since the type can change, perhaps having an listener might be better? we do set this context key - doesn't look like there's a way to access context keys via api though atm
since things can be achieved with this upcoming change (check or /), I'm not sure we want to add more to the API just to handle this case.
this still makes it sound like the current API is buggy and that the proposed event is also a band-aid for that. So, our ask is to explore how to be correct on start. How long does it usually take to know what the default shell is How long does it take when configured by the user Can that value be cached (iff it's expensive) per session or across session?
looks like it typically takes ~100ms on Windows but some reloads it was higher at 250ms. What I really think we shouldn't do is block the extension host init on the pty host process launching. Simple caching should work well though as it rarely changes once set
I would agree but I wonder when does the pty-host launch? Is that with the first renderer? There might be all the time in world to get the value ready while we start the renderer, load its code, digest extension data, launch the extension host etc pp. I want us to know this
It starts up on shared process init: Might be wrong, but I looked at init data and I don't think it's pulling anything from other processes right now? The extension host service inits on , and while the shared process does start on workbench creation which is before then, blocking it on anything related to process communication feels like a bad idea to me. What if the process and/or IPC takes unusually long for whatever reason (Windows process overhead, remote with slow connection, etc.)? If anything we should be trying to get the extension host starting up faster.
Of course. But as matter of fact we have the API. We either deprecate it because we cannot implement it correctly or we understand for real what a correct implementation will cost. This is the context (check F1 Startup Performance) The shared process runs in parallel, so it can do stuff while the renderer loads its code, gets stuff ready etc. For orientation: on my machine it takes ~420ms to reach the -phase. We then start the extension host worker/processes which take another 293ms (web) or 364ms (nodejs) to get their init data. From starting the renderer that gives ~750ms. how do I figure out how long resolving the default shell takes on my machine so that I can put this in context? <img width="574" alt="Screenshot 2022-09-26 at 16 38 00" src="https://user-"<img width="543" alt="Screenshot 2022-09-26 at 16 37 46" src="https://user-"
I was measuring the time it takes to run to see how long it takes: The service is registered here for web: Here for desktop:
Update since this was last discussed: the pty host now doesn't necessarily start up, however profiles are now always detected on the main/server procs, not the pty host: Needs a final decision whether we want to block the exthost startup on terminal profile resolving.
I measured the time it takes to on the main process which is necessary in order to get the default shell and it came out to 55ms. Given this, I still think the impact is too great when doing this eagerly on the main process during startup and before the extension host is launched. Caching it optimistically across sessions is a good idea though. Created to track that separately from the event.
Can we put these numbers in perspective, e.g how about setting perf-markers so that they make it into telemetry so that we have a better view. 50ms isn't slow because from main, we start the renderer, we load the renderer code which are all opportunities to run this in parallel so that the results from are ready before we even attempt to start the EH process (which usually happens ~2sec after starting main)
Let's leave this issue open because is still empty after startup but now we have the event which also serves as a workaround
I had a look at this and it's not as easy as I expected to get the profile in main as currently it depends upon the workspace and the renderer process evaluating parts of it before being handed off the the main process. I'm closing this as finalized because the issue where the initial value is an empty string is separate from the event API, plus it's tracked in the targeted issue

Discussion:
"taskPresentationGroup", "terminalDataWriteEvent", "terminalDimensions", <ins> "envShellEvent", </ins> "testCoverage", "testObserver", "textSearchProvider",

get shell() { return extHostTerminalService.getDefaultShell(false); }, <ins> get onDidChangeShell() { checkProposedApiEnabled(extension, 'envShellEvent'); return extHostTerminalService.onDidChangeShell; }, </ins> get isTelemetryEnabled() { return extHostTelemetry.getTelemetryConfiguration(); },

onDidChangeTerminalDimensions: Event<vscode.TerminalDimensionsChangeEvent>; onDidChangeTerminalState: Event<vscode.Terminal>; onDidWriteTerminalData: Event<vscode.TerminalDataWriteEvent>; <ins> onDidChangeShell: Event<string>; </ins> createTerminal(name?: string, shellPath?: string, shellArgs?: readonly string[] | string): vscode.Terminal; createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal;

readonly onDidChangeTerminalState = this._onDidChangeTerminalState.event; protected readonly _onDidWriteTerminalData: Emitter<vscode.TerminalDataWriteEvent>; get onDidWriteTerminalData(): Event<vscode.TerminalDataWriteEvent> { return this._onDidWriteTerminalData.event; } <ins> protected readonly _onDidChangeShell = new Emitter<string>(); readonly onDidChangeShell = this._onDidChangeShell.event; </ins> constructor( supportsProcesses: boolean,

} public $acceptDefaultProfile(profile: ITerminalProfile, automationProfile: ITerminalProfile): void { <ins> const oldProfile = this._defaultProfile; </ins> this._defaultProfile = profile; this._defaultAutomationProfile = automationProfile; <ins> if (oldProfile?.path !== profile.path) { this._onDidChangeShell.fire(profile.path); } </ins> } private _setEnvironmentVariableCollection(extensionIdentifier: string, collection: EnvironmentVariableCollection): void {

documentPaste: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.documentPaste.d.ts', editSessionIdentityProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editSessionIdentityProvider.d.ts', editorInsets: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editorInsets.d.ts', <ins> envShellEvent: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.envShellEvent.d.ts', </ins> extensionRuntime: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.extensionRuntime.d.ts', extensionsAny: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.extensionsAny.d.ts', externalUriOpener: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.externalUriOpener.d.ts',

<ins> /*--------------------------------------------------------------------------------------------- *  Copyright (c) Microsoft Corporation. All rights reserved. *  Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ declare module 'vscode' { // See https://github.com/microsoft/vscode/issues/160694 export namespace env { /** * An {@link Event} which fires when the default shell changes. */ export const onDidChangeShell: Event<string>; } } </ins>