src/vs/workbench/contrib/terminal/browser/terminalInstance.ts/TerminalInstance/_createProcessManager
class TerminalInstance:	protected _createProcessManager(): TerminalProcessManager {
		let deserializedCollections: ReadonlyMap<string, IEnvironmentVariableCollection> | undefined;
		if (this.shellLaunchConfig.attachPersistentProcess?.environmentVariableCollections) {
			deserializedCollections = deserializeEnvironmentVariableCollections(this.shellLaunchConfig.attachPersistentProcess.environmentVariableCollections);
		}
		const processManager = this._instantiationService.createInstance(TerminalProcessManager, this._instanceId, this._configHelper, this.shellLaunchConfig?.cwd, deserializedCollections);
		this.capabilities.add(processManager.capabilities);
		processManager.onProcessReady(async (e) => {
			this._onProcessIdReady.fire(this);
			this._initialCwd = await this.getInitialCwd();
			// Set the initial name based on the _resolved_ shell launch config, this will also
			// ensure the resolved icon gets shown
			if (!this._labelComputer) {
				this._labelComputer = this._register(new TerminalLabelComputer(this._configHelper, this, this._workspaceContextService));
				this._labelComputer.onDidChangeLabel(e => {
					this._title = e.title;
					this._description = e.description;
					this._onTitleChanged.fire(this);
				});
			}
			if (this._shellLaunchConfig.name) {
				this.refreshTabLabels(this._shellLaunchConfig.name, TitleEventSource.Api);
			} else {
				// Listen to xterm.js' sequence title change event, trigger this async to ensure
				// _xtermReadyPromise is ready constructed since this is called from the ctor
				setTimeout(() => {
					this._xtermReadyPromise.then(xterm => {
						this._messageTitleDisposable = xterm.raw.onTitleChange(e => this._onTitleChange(e));
					});
				});
				this.refreshTabLabels(this._shellLaunchConfig.executable, TitleEventSource.Process);
			}
		});
		processManager.onProcessExit(exitCode => this._onProcessExit(exitCode));
		processManager.onDidChangeProperty(({ type, value }) => {
			switch (type) {
				case ProcessPropertyType.Cwd:
					this._cwd = value;
					this._labelComputer?.refreshLabel();
					break;
				case ProcessPropertyType.InitialCwd:
					this._initialCwd = value;
					this._cwd = this._initialCwd;
					this.refreshTabLabels(this.title, TitleEventSource.Config);
					break;
				case ProcessPropertyType.Title:
					this.refreshTabLabels(value ? value : '', TitleEventSource.Process);
					break;
				case ProcessPropertyType.OverrideDimensions:
					this.setOverrideDimensions(value, true);
					break;
				case ProcessPropertyType.ResolvedShellLaunchConfig:
					this._setResolvedShellLaunchConfig(value);
					break;
				case ProcessPropertyType.ShellType:
					this.setShellType(value);
					break;
				case ProcessPropertyType.HasChildProcesses:
					this._onDidChangeHasChildProcesses.fire(value);
					break;
				case ProcessPropertyType.UsedShellIntegrationInjection:
					this._usedShellIntegrationInjection = true;
					break;
			}
		});

		processManager.onProcessData(ev => {
			this._initialDataEvents?.push(ev.data);
			this._onData.fire(ev.data);
		});
		processManager.onEnvironmentVariableInfoChanged(e => this._onEnvironmentVariableInfoChanged(e));
		processManager.onPtyDisconnect(() => {
			if (this.xterm) {
				this.xterm.raw.options.disableStdin = true;
			}
			this.statusList.add({
				id: TerminalStatus.Disconnected,
				severity: Severity.Error,
				icon: Codicon.debugDisconnect,
				tooltip: nls.localize('disconnectStatus', "Lost connection to process")
			});
		});
		processManager.onPtyReconnect(() => {
			if (this.xterm) {
				this.xterm.raw.options.disableStdin = false;
			}
			this.statusList.remove(TerminalStatus.Disconnected);
		});

		return processManager;
	}