Move pty to shared process

This commit is contained in:
Daniel Imms
2021-02-10 14:03:34 -08:00
parent 1abb2d9534
commit 67dda13a3a
10 changed files with 148 additions and 70 deletions
@@ -81,6 +81,10 @@ import { DeprecatedExtensionsCleaner } from 'vs/code/electron-browser/sharedProc
import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { join } from 'vs/base/common/path';
import { LocalPtyChannel } from 'vs/platform/terminal/electron-browser/terminalIpc';
import { TerminalIpcChannels } from 'vs/platform/terminal/common/terminal';
import { LocalPtyService } from 'vs/platform/terminal/electron-browser/localPtyService';
import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal';
class SharedProcessMain extends Disposable {
@@ -259,6 +263,10 @@ class SharedProcessMain extends Disposable {
services.set(IUserDataSyncResourceEnablementService, new SyncDescriptor(UserDataSyncResourceEnablementService));
services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService));
// Terminal
// TODO: Move out of electron-main
services.set(ILocalPtyService, new SyncDescriptor(LocalPtyService));
return new InstantiationService(services);
}
@@ -304,6 +312,11 @@ class SharedProcessMain extends Disposable {
const userDataAutoSync = this._register(accessor.get(IInstantiationService).createInstance(UserDataAutoSyncService));
const userDataAutoSyncChannel = new UserDataAutoSyncChannel(userDataAutoSync);
this.server.registerChannel('userDataAutoSync', userDataAutoSyncChannel);
// Terminal
const localPtyMainService = accessor.get(ILocalPtyService);
const localPtyMainChannel = new LocalPtyChannel(localPtyMainService);
this.server.registerChannel(TerminalIpcChannels.LocalPty, localPtyMainChannel);
}
private registerErrorHandler(logService: ILogService): void {
-6
View File
@@ -89,7 +89,6 @@ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cance
import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust';
import { ExtensionUrlTrustService } from 'vs/platform/extensionManagement/node/extensionUrlTrustService';
import { once } from 'vs/base/common/functional';
import { ILocalPtyMainService, LocalPtyMainService } from 'vs/platform/terminal/electron-main/localPtyMainService';
export class CodeApplication extends Disposable {
private windowsMainService: IWindowsMainService | undefined;
@@ -528,7 +527,6 @@ export class CodeApplication extends Disposable {
services.set(ILaunchMainService, new SyncDescriptor(LaunchMainService));
services.set(IDiagnosticsService, ProxyChannel.toService(getDelayedChannel(sharedProcessReady.then(client => client.getChannel('diagnostics')))));
services.set(ILocalPtyMainService, new SyncDescriptor(LocalPtyMainService));
services.set(IIssueMainService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv]));
services.set(IEncryptionMainService, new SyncDescriptor(EncryptionMainService, [machineId]));
services.set(IKeyboardLayoutMainService, new SyncDescriptor(KeyboardLayoutMainService));
@@ -616,10 +614,6 @@ export class CodeApplication extends Disposable {
const updateChannel = new UpdateChannel(updateService);
electronIpcServer.registerChannel('update', updateChannel);
const localPtyMainService = accessor.get(ILocalPtyMainService);
const localPtyChannel = createChannelReceiver(localPtyMainService);
electronIpcServer.registerChannel('localPty', localPtyChannel);
const issueMainService = accessor.get(IIssueMainService);
const issueChannel = ProxyChannel.fromService(issueMainService);
electronIpcServer.registerChannel('issue', issueChannel);
+11 -7
View File
@@ -7,15 +7,19 @@ import { Event } from 'vs/base/common/event';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
export interface ICommonLocalPtyService {
export enum TerminalIpcChannels {
LocalPty = 'localPty'
}
export interface ILocalPtyService {
readonly _serviceBrand: undefined;
readonly onProcessData: Event<{ id: number, event: IProcessDataEvent | string }>;
readonly onProcessExit: Event<{ id: number, event: number | undefined }>;
readonly onProcessReady: Event<{ id: number, event: { pid: number, cwd: string } }>;
readonly onProcessTitleChanged: Event<{ id: number, event: string }>;
readonly onProcessOverrideDimensions: Event<{ id: number, event: ITerminalDimensionsOverride | undefined }>;
readonly onProcessResolvedShellLaunchConfig: Event<{ id: number, event: IShellLaunchConfig }>;
// readonly onProcessData: Event<{ id: number, event: IProcessDataEvent | string }>;
// readonly onProcessExit: Event<{ id: number, event: number | undefined }>;
// readonly onProcessReady: Event<{ id: number, event: { pid: number, cwd: string } }>;
// readonly onProcessTitleChanged: Event<{ id: number, event: string }>;
// readonly onProcessOverrideDimensions: Event<{ id: number, event: ITerminalDimensionsOverride | undefined }>;
// readonly onProcessResolvedShellLaunchConfig: Event<{ id: number, event: IShellLaunchConfig }>;
createProcess(
shellLaunchConfig: IShellLaunchConfig,
@@ -3,37 +3,31 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
import { ICommonLocalPtyService, IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError } from 'vs/platform/terminal/common/terminal';
import { ILocalPtyService, IShellLaunchConfig, ITerminalChildProcess, ITerminalLaunchError } from 'vs/platform/terminal/common/terminal';
import { TerminalProcess } from 'vs/platform/terminal/node/terminalProcess';
export const ILocalPtyMainService = createDecorator<ILocalPtyMainService>('localPtyMainService');
export interface ILocalPtyMainService extends ICommonLocalPtyService { }
let currentLocalPtyId = 0;
export class LocalPtyMainService extends Disposable implements ICommonLocalPtyService {
export class LocalPtyService extends Disposable implements ILocalPtyService {
declare readonly _serviceBrand: undefined;
private readonly _localPtys: Map<number, ITerminalChildProcess> = new Map();
private readonly _onProcessData = this._register(new Emitter<{ id: number, event: IProcessDataEvent | string }>());
readonly onProcessData = this._onProcessData.event;
private readonly _onProcessExit = this._register(new Emitter<{ id: number, event: number | undefined }>());
readonly onProcessExit = this._onProcessExit.event;
private readonly _onProcessReady = this._register(new Emitter<{ id: number, event: { pid: number, cwd: string } }>());
readonly onProcessReady = this._onProcessReady.event;
private readonly _onProcessTitleChanged = this._register(new Emitter<{ id: number, event: string }>());
readonly onProcessTitleChanged = this._onProcessTitleChanged.event;
private readonly _onProcessOverrideDimensions = this._register(new Emitter<{ id: number, event: ITerminalDimensionsOverride | undefined }>());
readonly onProcessOverrideDimensions = this._onProcessOverrideDimensions.event;
private readonly _onProcessResolvedShellLaunchConfig = this._register(new Emitter<{ id: number, event: IShellLaunchConfig }>());
readonly onProcessResolvedShellLaunchConfig = this._onProcessResolvedShellLaunchConfig.event;
// private readonly _onProcessData = this._register(new Emitter<{ id: number, event: IProcessDataEvent | string }>());
// readonly onProcessData = this._onProcessData.event;
// private readonly _onProcessExit = this._register(new Emitter<{ id: number, event: number | undefined }>());
// readonly onProcessExit = this._onProcessExit.event;
// private readonly _onProcessReady = this._register(new Emitter<{ id: number, event: { pid: number, cwd: string } }>());
// readonly onProcessReady = this._onProcessReady.event;
// private readonly _onProcessTitleChanged = this._register(new Emitter<{ id: number, event: string }>());
// readonly onProcessTitleChanged = this._onProcessTitleChanged.event;
// private readonly _onProcessOverrideDimensions = this._register(new Emitter<{ id: number, event: ITerminalDimensionsOverride | undefined }>());
// readonly onProcessOverrideDimensions = this._onProcessOverrideDimensions.event;
// private readonly _onProcessResolvedShellLaunchConfig = this._register(new Emitter<{ id: number, event: IShellLaunchConfig }>());
// readonly onProcessResolvedShellLaunchConfig = this._onProcessResolvedShellLaunchConfig.event;
constructor(
@ILogService private readonly _logService: ILogService
@@ -43,17 +37,18 @@ export class LocalPtyMainService extends Disposable implements ICommonLocalPtySe
async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, executableEnv: IProcessEnvironment, windowsEnableConpty: boolean): Promise<number> {
const id = ++currentLocalPtyId;
console.log('LocalPtyMainService#createProcess ' + id, shellLaunchConfig, cwd, cols);
const process = new TerminalProcess(shellLaunchConfig, cwd, cols, rows, env, executableEnv, windowsEnableConpty, this._logService);
process.onProcessData(event => this._onProcessData.fire({ id, event }));
process.onProcessExit(event => this._onProcessExit.fire({ id, event }));
process.onProcessReady(event => this._onProcessReady.fire({ id, event }));
process.onProcessTitleChanged(event => this._onProcessTitleChanged.fire({ id, event }));
if (process.onProcessOverrideDimensions) {
process.onProcessOverrideDimensions(event => this._onProcessOverrideDimensions.fire({ id, event }));
}
if (process.onProcessResolvedShellLaunchConfig) {
process.onProcessResolvedShellLaunchConfig(event => this._onProcessResolvedShellLaunchConfig.fire({ id, event }));
}
// process.onProcessData(event => this._onProcessData.fire({ id, event }));
// process.onProcessExit(event => this._onProcessExit.fire({ id, event }));
// process.onProcessReady(event => this._onProcessReady.fire({ id, event }));
// process.onProcessTitleChanged(event => this._onProcessTitleChanged.fire({ id, event }));
// if (process.onProcessOverrideDimensions) {
// process.onProcessOverrideDimensions(event => this._onProcessOverrideDimensions.fire({ id, event }));
// }
// if (process.onProcessResolvedShellLaunchConfig) {
// process.onProcessResolvedShellLaunchConfig(event => this._onProcessResolvedShellLaunchConfig.fire({ id, event }));
// }
this._localPtys.set(id, process);
return id;
}
@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { ILocalPtyService } from 'vs/platform/terminal/common/terminal';
export class LocalPtyChannel extends Disposable implements IServerChannel {
constructor(
private readonly _localPtyMainService: ILocalPtyService
) {
super();
}
listen(_: unknown, event: string): Event<any> {
throw new Error(`Event not found: ${event}`);
}
async call(_: unknown, command: string, arg?: any): Promise<any> {
switch (command) {
case '$createProcess': return this._localPtyMainService.createProcess(...arg as [any, any, any, any, any, any, any]);
case '$start': return this._localPtyMainService.start(...(arg as [any]));
// TODO: Fill in other calls
default:
throw new Error(`Call not found: ${command}`);
}
}
}
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ICommonLocalPtyService } from 'vs/platform/terminal/common/terminal';
import { ILocalPtyService as ICommonLocalPtyService } from 'vs/platform/terminal/common/terminal';
export const ILocalPtyService = createDecorator<ILocalPtyService>('localPtyService');
@@ -31,12 +31,12 @@ export class TerminalProcessMainProxy extends Disposable implements ITerminalChi
@ILocalPtyService private readonly _localPtyService: ILocalPtyService
) {
super();
this._localPtyService.onProcessData(e => e.id === this._localPtyId && this._onProcessData.fire(e.event));
this._localPtyService.onProcessExit(e => e.id === this._localPtyId && this._onProcessExit.fire(e.event));
this._localPtyService.onProcessReady(e => e.id === this._localPtyId && this._onProcessReady.fire(e.event));
this._localPtyService.onProcessTitleChanged(e => e.id === this._localPtyId && this._onProcessTitleChanged.fire(e.event));
this._localPtyService.onProcessOverrideDimensions(e => e.id === this._localPtyId && this._onProcessOverrideDimensions.fire(e.event));
this._localPtyService.onProcessResolvedShellLaunchConfig(e => e.id === this._localPtyId && this._onProcessResolvedShellLaunchConfig.fire(e.event));
// this._localPtyService.onProcessData(e => e.id === this._localPtyId && this._onProcessData.fire(e.event));
// this._localPtyService.onProcessExit(e => e.id === this._localPtyId && this._onProcessExit.fire(e.event));
// this._localPtyService.onProcessReady(e => e.id === this._localPtyId && this._onProcessReady.fire(e.event));
// this._localPtyService.onProcessTitleChanged(e => e.id === this._localPtyId && this._onProcessTitleChanged.fire(e.event));
// this._localPtyService.onProcessOverrideDimensions(e => e.id === this._localPtyId && this._onProcessOverrideDimensions.fire(e.event));
// this._localPtyService.onProcessResolvedShellLaunchConfig(e => e.id === this._localPtyId && this._onProcessResolvedShellLaunchConfig.fire(e.event));
}
start(): Promise<ITerminalLaunchError | { remoteTerminalId: number; } | undefined> {
@@ -1,18 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal';
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
import { createChannelSender } from 'vs/base/parts/ipc/common/ipc';
// @ts-ignore: interface is implemented via proxy
export class LocalPtyService implements ILocalPtyService {
declare readonly _serviceBrand: undefined;
constructor(@IMainProcessService mainProcessService: IMainProcessService) {
return createChannelSender<ILocalPtyService>(mainProcessService.getChannel('localPty'));
}
}
@@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal';
import { IShellLaunchConfig, ITerminalLaunchError, TerminalIpcChannels } from 'vs/platform/terminal/common/terminal';
import { ISharedProcessService } from 'vs/platform/ipc/electron-sandbox/sharedProcessService';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IProcessEnvironment } from 'vs/base/common/platform';
export class LocalPtyServiceProxy implements ILocalPtyService {
declare readonly _serviceBrand: undefined;
private readonly _channel: IChannel;
constructor(
@ISharedProcessService sharedProcessService: ISharedProcessService
) {
this._channel = sharedProcessService.getChannel(TerminalIpcChannels.LocalPty);
}
// onProcessData: Event<{ id: number; event: string | IProcessDataEvent; }>;
// onProcessExit: Event<{ id: number; event: number | undefined; }>;
// onProcessReady: Event<{ id: number; event: { pid: number; cwd: string; }; }>;
// onProcessTitleChanged: Event<{ id: number; event: string; }>;
// onProcessOverrideDimensions: Event<{ id: number; event: ITerminalDimensionsOverride | undefined; }>;
// onProcessResolvedShellLaunchConfig: Event<{ id: number; event: IShellLaunchConfig; }>;
createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, executableEnv: IProcessEnvironment, windowsEnableConpty: boolean): Promise<number> {
return this._channel.call('$createProcess', Array.prototype.slice.call(arguments));
}
start(id: number): Promise<ITerminalLaunchError | { remoteTerminalId: number; } | undefined> {
return this._channel.call('$start', Array.prototype.slice.call(arguments));
}
shutdown(id: number, immediate: boolean): Promise<void> {
return this._channel.call('$shutdown', Array.prototype.slice.call(arguments));
}
input(id: number, data: string): Promise<void> {
return this._channel.call('$input', Array.prototype.slice.call(arguments));
}
resize(id: number, cols: number, rows: number): Promise<void> {
return this._channel.call('$resize', Array.prototype.slice.call(arguments));
}
acknowledgeDataEvent(id: number, charCount: number): Promise<void> {
return this._channel.call('$acknowledgeDataEvents', Array.prototype.slice.call(arguments));
}
getInitialCwd(id: number): Promise<string> {
return this._channel.call('$getInitialCwd', Array.prototype.slice.call(arguments));
}
getCwd(id: number): Promise<string> {
return this._channel.call('$getCwd', Array.prototype.slice.call(arguments));
}
getLatency(id: number): Promise<number> {
return this._channel.call('$getLatency', Array.prototype.slice.call(arguments));
}
}
@@ -5,6 +5,6 @@
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal';
import { LocalPtyService } from 'vs/workbench/contrib/terminal/electron-sandbox/localPtyService';
import { LocalPtyServiceProxy } from 'vs/workbench/contrib/terminal/electron-sandbox/localPtyServiceProxy';
registerSingleton(ILocalPtyService, LocalPtyService, true);
registerSingleton(ILocalPtyService, LocalPtyServiceProxy, true);