|
4 | 4 | *--------------------------------------------------------------------------------------------*/
|
5 | 5 |
|
6 | 6 | import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
| 7 | +import { parsePtyHostDebugPort } from 'vs/platform/environment/node/environmentService'; |
| 8 | +import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; |
| 9 | +import { ILogService } from 'vs/platform/log/common/log'; |
| 10 | +import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; |
7 | 11 | import { IReconnectConstants } from 'vs/platform/terminal/common/terminal';
|
8 |
| -import { NodePtyHostStarter } from 'vs/platform/terminal/node/nodePtyHostStarter'; |
9 | 12 | import { IPtyHostConnection, IPtyHostStarter } from 'vs/platform/terminal/node/ptyHost';
|
10 |
| -// import { FileAccess } from 'vs/base/common/network'; |
11 |
| -// import { Client, IIPCOptions } from 'vs/base/parts/ipc/node/ipc.cp'; |
12 |
| -// import { parsePtyHostDebugPort } from 'vs/platform/environment/node/environmentService'; |
13 |
| -// import { UtilityProcess } from 'vs/platform/utilityProcess/electron-main/utilityProcess'; |
| 13 | +import { UtilityProcess } from 'vs/platform/utilityProcess/electron-main/utilityProcess'; |
| 14 | +import { Client as MessagePortClient } from 'vs/base/parts/ipc/electron-main/ipc.mp'; |
| 15 | +import { IpcMainEvent } from 'electron'; |
| 16 | +import { validatedIpcMain } from 'vs/base/parts/ipc/electron-main/ipcMain'; |
| 17 | +import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; |
| 18 | +import { Emitter } from 'vs/base/common/event'; |
14 | 19 |
|
15 | 20 | export class ElectronPtyHostStarter implements IPtyHostStarter {
|
16 | 21 |
|
17 |
| - // private utilityProcess: UtilityProcess | undefined = undefined; |
| 22 | + private utilityProcess: UtilityProcess | undefined = undefined; |
| 23 | + |
| 24 | + private readonly _onBeforeWindowConnection = new Emitter<void>(); |
| 25 | + readonly onBeforeWindowConnection = this._onBeforeWindowConnection.event; |
| 26 | + private readonly _onWillShutdown = new Emitter<void>(); |
| 27 | + readonly onWillShutdown = this._onWillShutdown.event; |
18 | 28 |
|
19 | 29 | constructor(
|
20 | 30 | private readonly _reconnectConstants: IReconnectConstants,
|
21 |
| - @IEnvironmentService private readonly _environmentService: INativeEnvironmentService |
| 31 | + @IEnvironmentService private readonly _environmentService: INativeEnvironmentService, |
| 32 | + @ILifecycleMainService private readonly _lifecycleMainService: ILifecycleMainService, |
| 33 | + @ILogService private readonly _logService: ILogService |
22 | 34 | ) {
|
| 35 | + this._lifecycleMainService.onWillShutdown(() => this._onWillShutdown.fire()); |
| 36 | + // Listen for new windows to establish connection directly to pty host |
| 37 | + validatedIpcMain.on('vscode:createPtyHostMessageChannel', (e, nonce) => this._onWindowConnection(e, nonce)); |
23 | 38 | }
|
24 | 39 |
|
25 | 40 | start(lastPtyId: number): IPtyHostConnection {
|
26 |
| - return new NodePtyHostStarter(this._reconnectConstants, this._environmentService).start(lastPtyId); |
27 |
| - |
28 |
| - // console.log('use utility proc'); |
29 |
| - |
30 |
| - // // TODO: Convert to use utility process |
31 |
| - // const opts: IIPCOptions = { |
32 |
| - // serverName: 'Pty Host', |
33 |
| - // args: ['--type=ptyHost', '--logsPath', this._environmentService.logsHome.fsPath], |
34 |
| - // env: { |
35 |
| - // VSCODE_LAST_PTY_ID: lastPtyId, |
36 |
| - // VSCODE_PTY_REMOTE: this._isRemote, |
37 |
| - // VSCODE_AMD_ENTRYPOINT: 'vs/platform/terminal/node/ptyHostMain', |
38 |
| - // VSCODE_PIPE_LOGGING: 'true', |
39 |
| - // VSCODE_VERBOSE_LOGGING: 'true', // transmit console logs from server to client, |
40 |
| - // VSCODE_RECONNECT_GRACE_TIME: this._reconnectConstants.graceTime, |
41 |
| - // VSCODE_RECONNECT_SHORT_GRACE_TIME: this._reconnectConstants.shortGraceTime, |
42 |
| - // VSCODE_RECONNECT_SCROLLBACK: this._reconnectConstants.scrollback |
43 |
| - // } |
44 |
| - // }; |
45 |
| - |
46 |
| - // const ptyHostDebug = parsePtyHostDebugPort(this._environmentService.args, this._environmentService.isBuilt); |
47 |
| - // if (ptyHostDebug) { |
48 |
| - // if (ptyHostDebug.break && ptyHostDebug.port) { |
49 |
| - // opts.debugBrk = ptyHostDebug.port; |
50 |
| - // } else if (!ptyHostDebug.break && ptyHostDebug.port) { |
51 |
| - // opts.debug = ptyHostDebug.port; |
52 |
| - // } |
53 |
| - // } |
54 |
| - |
55 |
| - // const client = new Client(FileAccess.asFileUri('bootstrap-fork').fsPath, opts); |
56 |
| - |
57 |
| - // return { |
58 |
| - // client, |
59 |
| - // dispose: client.dispose, |
60 |
| - // onDidProcessExit: client.onDidProcessExit |
61 |
| - // }; |
| 41 | + this.utilityProcess = new UtilityProcess(this._logService, NullTelemetryService, this._lifecycleMainService); |
| 42 | + |
| 43 | + const inspectParams = parsePtyHostDebugPort(this._environmentService.args, this._environmentService.isBuilt); |
| 44 | + let execArgv: string[] | undefined = undefined; |
| 45 | + if (inspectParams) { |
| 46 | + execArgv = ['--nolazy']; |
| 47 | + if (inspectParams.break) { |
| 48 | + execArgv.push(`--inspect-brk=${inspectParams.port}`); |
| 49 | + } else if (!inspectParams.break) { |
| 50 | + execArgv.push(`--inspect=${inspectParams.port}`); |
| 51 | + } |
| 52 | + } |
| 53 | + |
| 54 | + this.utilityProcess.start({ |
| 55 | + type: 'ptyHost', |
| 56 | + entryPoint: 'vs/platform/terminal/node/ptyHostMain', |
| 57 | + payload: this._createPtyHostConfiguration(lastPtyId), |
| 58 | + execArgv |
| 59 | + }); |
| 60 | + |
| 61 | + const port = this.utilityProcess.connect(); |
| 62 | + const client = new MessagePortClient(port, 'ptyHost'); |
| 63 | + |
| 64 | + const store = new DisposableStore(); |
| 65 | + store.add(client); |
| 66 | + store.add(this.utilityProcess); |
| 67 | + store.add(toDisposable(() => { |
| 68 | + validatedIpcMain.removeHandler('vscode:createPtyHostMessageChannel'); |
| 69 | + this.utilityProcess = undefined; |
| 70 | + })); |
| 71 | + |
| 72 | + return { |
| 73 | + client, |
| 74 | + store, |
| 75 | + onDidProcessExit: this.utilityProcess.onExit |
| 76 | + }; |
| 77 | + } |
| 78 | + |
| 79 | + private _createPtyHostConfiguration(lastPtyId: number) { |
| 80 | + return { |
| 81 | + VSCODE_LAST_PTY_ID: lastPtyId, |
| 82 | + VSCODE_AMD_ENTRYPOINT: 'vs/platform/terminal/node/ptyHostMain', |
| 83 | + VSCODE_PIPE_LOGGING: 'true', |
| 84 | + VSCODE_VERBOSE_LOGGING: 'true', // transmit console logs from server to client, |
| 85 | + VSCODE_RECONNECT_GRACE_TIME: this._reconnectConstants.graceTime, |
| 86 | + VSCODE_RECONNECT_SHORT_GRACE_TIME: this._reconnectConstants.shortGraceTime, |
| 87 | + VSCODE_RECONNECT_SCROLLBACK: this._reconnectConstants.scrollback |
| 88 | + }; |
| 89 | + } |
| 90 | + |
| 91 | + private _onWindowConnection(e: IpcMainEvent, nonce: string) { |
| 92 | + this._onBeforeWindowConnection.fire(); |
| 93 | + |
| 94 | + const port = this.utilityProcess!.connect(); |
| 95 | + |
| 96 | + // Check back if the requesting window meanwhile closed |
| 97 | + // Since shared process is delayed on startup there is |
| 98 | + // a chance that the window close before the shared process |
| 99 | + // was ready for a connection. |
| 100 | + |
| 101 | + if (e.sender.isDestroyed()) { |
| 102 | + port.close(); |
| 103 | + return; |
| 104 | + } |
| 105 | + |
| 106 | + e.sender.postMessage('vscode:createPtyHostMessageChannelResult', nonce, [port]); |
62 | 107 | }
|
63 | 108 | }
|
0 commit comments