src/vs/platform/terminal/node/terminalProcess.ts/TerminalProcess/setupPtyProcess
class TerminalProcess:	private async setupPtyProcess(
		shellLaunchConfig: IShellLaunchConfig,
		options: pty.IPtyForkOptions,
		shellIntegrationInjection: IShellIntegrationConfigInjection | undefined
	): Promise<void> {
		const args = shellIntegrationInjection?.newArgs || shellLaunchConfig.args || [];
		await this._throttleKillSpawn();
		this._logService.trace('IPty#spawn', shellLaunchConfig.executable, args, options);
		const ptyProcess = (await import('node-pty')).spawn(shellLaunchConfig.executable!, args, options);
		this._ptyProcess = ptyProcess;
		this._childProcessMonitor = this._register(new ChildProcessMonitor(ptyProcess.pid, this._logService));
		this._childProcessMonitor.onDidChangeHasChildProcesses(value => this._onDidChangeProperty.fire({ type: ProcessPropertyType.HasChildProcesses, value }));
		this._processStartupComplete = new Promise<void>(c => {
			this.onProcessReady(() => c());
		});
		ptyProcess.onData(data => {
			// Handle flow control
			this._unacknowledgedCharCount += data.length;
			if (!this._isPtyPaused && this._unacknowledgedCharCount > FlowControlConstants.HighWatermarkChars) {
				this._logService.trace(`Flow control: Pause (${this._unacknowledgedCharCount} > ${FlowControlConstants.HighWatermarkChars})`);
				this._isPtyPaused = true;
				ptyProcess.pause();
			}

			// Refire the data event
			this._onProcessData.fire(data);
			if (this._closeTimeout) {
				this._queueProcessExit();
			}
			this._windowsShellHelper?.checkShell();
			this._childProcessMonitor?.handleOutput();
		});
		ptyProcess.onExit(e => {
			this._exitCode = e.exitCode;
			this._queueProcessExit();
		});
		this._sendProcessId(ptyProcess.pid);
		this._setupTitlePolling(ptyProcess);
	}