mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
ensureNoDisposablesAreLeakedInTestSuite: ipc (#192570)
* ensureNoDisposablesAreLeakedInTestSuite: ipc related to #190503 * debt - proxy services need to ask for disposables --------- Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com>
This commit is contained in:
@@ -394,7 +394,7 @@ export namespace Event {
|
||||
* this.onInstallExtension = Event.buffer(service.onInstallExtension, true);
|
||||
* ```
|
||||
*/
|
||||
export function buffer<T>(event: Event<T>, flushAfterTimeout = false, _buffer: T[] = []): Event<T> {
|
||||
export function buffer<T>(event: Event<T>, flushAfterTimeout = false, _buffer: T[] = [], disposable?: DisposableStore): Event<T> {
|
||||
let buffer: T[] | null = _buffer.slice();
|
||||
|
||||
let listener: IDisposable | null = event(e => {
|
||||
@@ -405,6 +405,10 @@ export namespace Event {
|
||||
}
|
||||
});
|
||||
|
||||
if (disposable) {
|
||||
disposable.add(listener);
|
||||
}
|
||||
|
||||
const flush = () => {
|
||||
buffer?.forEach(e => emitter.fire(e));
|
||||
buffer = null;
|
||||
@@ -414,6 +418,9 @@ export namespace Event {
|
||||
onWillAddFirstListener() {
|
||||
if (!listener) {
|
||||
listener = event(e => emitter.fire(e));
|
||||
if (disposable) {
|
||||
disposable.add(listener);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -435,6 +442,10 @@ export namespace Event {
|
||||
}
|
||||
});
|
||||
|
||||
if (disposable) {
|
||||
disposable.add(emitter);
|
||||
}
|
||||
|
||||
return emitter.event;
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -427,7 +427,6 @@ export class ChannelServer<TContext = string> implements IChannelServer<TContext
|
||||
|
||||
promise.then(data => {
|
||||
this.sendResponse(<IRawResponse>{ id, data, type: ResponseType.PromiseSuccess });
|
||||
this.activeRequests.delete(request.id);
|
||||
}, err => {
|
||||
if (err instanceof Error) {
|
||||
this.sendResponse(<IRawResponse>{
|
||||
@@ -440,7 +439,8 @@ export class ChannelServer<TContext = string> implements IChannelServer<TContext
|
||||
} else {
|
||||
this.sendResponse(<IRawResponse>{ id, data: err, type: ResponseType.PromiseErrorObj });
|
||||
}
|
||||
|
||||
}).finally(() => {
|
||||
disposable.dispose();
|
||||
this.activeRequests.delete(request.id);
|
||||
});
|
||||
|
||||
@@ -639,7 +639,10 @@ export class ChannelClient implements IChannelClient, IDisposable {
|
||||
this.activeRequests.add(disposable);
|
||||
});
|
||||
|
||||
return result.finally(() => { this.activeRequests.delete(disposable); });
|
||||
return result.finally(() => {
|
||||
disposable.dispose();
|
||||
this.activeRequests.delete(disposable);
|
||||
});
|
||||
}
|
||||
|
||||
private requestEvent(channelName: string, name: string, arg?: any): Event<any> {
|
||||
@@ -795,6 +798,8 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
private readonly _onDidRemoveConnection = new Emitter<Connection<TContext>>();
|
||||
readonly onDidRemoveConnection: Event<Connection<TContext>> = this._onDidRemoveConnection.event;
|
||||
|
||||
private disposables = new DisposableStore();
|
||||
|
||||
get connections(): Connection<TContext>[] {
|
||||
const result: Connection<TContext>[] = [];
|
||||
this._connections.forEach(ctx => result.push(ctx));
|
||||
@@ -802,10 +807,10 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
}
|
||||
|
||||
constructor(onDidClientConnect: Event<ClientConnectionEvent>) {
|
||||
onDidClientConnect(({ protocol, onDidClientDisconnect }) => {
|
||||
this.disposables.add(onDidClientConnect(({ protocol, onDidClientDisconnect }) => {
|
||||
const onFirstMessage = Event.once(protocol.onMessage);
|
||||
|
||||
onFirstMessage(msg => {
|
||||
this.disposables.add(onFirstMessage(msg => {
|
||||
const reader = new BufferReader(msg);
|
||||
const ctx = deserialize(reader) as TContext;
|
||||
|
||||
@@ -818,14 +823,14 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
this._connections.add(connection);
|
||||
this._onDidAddConnection.fire(connection);
|
||||
|
||||
onDidClientDisconnect(() => {
|
||||
this.disposables.add(onDidClientDisconnect(() => {
|
||||
channelServer.dispose();
|
||||
channelClient.dispose();
|
||||
this._connections.delete(connection);
|
||||
this._onDidRemoveConnection.fire(connection);
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -879,7 +884,7 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
|
||||
private getMulticastEvent<T extends IChannel>(channelName: string, clientFilter: (client: Client<TContext>) => boolean, eventName: string, arg: any): Event<T> {
|
||||
const that = this;
|
||||
let disposables = new DisposableStore();
|
||||
let disposables: DisposableStore | undefined;
|
||||
|
||||
// Create an emitter which hooks up to all clients
|
||||
// as soon as first listener is added. It also
|
||||
@@ -922,7 +927,8 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
disposables.add(eventMultiplexer);
|
||||
},
|
||||
onDidRemoveLastListener: () => {
|
||||
disposables.dispose();
|
||||
disposables?.dispose();
|
||||
disposables = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -932,14 +938,21 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
registerChannel(channelName: string, channel: IServerChannel<TContext>): void {
|
||||
this.channels.set(channelName, channel);
|
||||
|
||||
this._connections.forEach(connection => {
|
||||
for (const connection of this._connections) {
|
||||
connection.channelServer.registerChannel(channelName, channel);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.channels.clear();
|
||||
this.disposables.dispose();
|
||||
|
||||
for (const connection of this._connections) {
|
||||
connection.channelClient.dispose();
|
||||
connection.channelServer.dispose();
|
||||
}
|
||||
|
||||
this._connections.clear();
|
||||
this.channels.clear();
|
||||
this._onDidAddConnection.dispose();
|
||||
this._onDidRemoveConnection.dispose();
|
||||
}
|
||||
@@ -1074,7 +1087,7 @@ export namespace ProxyChannel {
|
||||
|
||||
export interface ICreateServiceChannelOptions extends IProxyOptions { }
|
||||
|
||||
export function fromService<TContext>(service: unknown, options?: ICreateServiceChannelOptions): IServerChannel<TContext> {
|
||||
export function fromService<TContext>(service: unknown, disposables: DisposableStore, options?: ICreateServiceChannelOptions): IServerChannel<TContext> {
|
||||
const handler = service as { [key: string]: unknown };
|
||||
const disableMarshalling = options && options.disableMarshalling;
|
||||
|
||||
@@ -1083,7 +1096,7 @@ export namespace ProxyChannel {
|
||||
const mapEventNameToEvent = new Map<string, Event<unknown>>();
|
||||
for (const key in handler) {
|
||||
if (propertyIsEvent(key)) {
|
||||
mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event<unknown>, true));
|
||||
mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event<unknown>, true, undefined, disposables));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,11 @@ import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { BufferReader, BufferWriter, ClientConnectionEvent, deserialize, IChannel, IMessagePassingProtocol, IPCClient, IPCServer, IServerChannel, ProxyChannel, serialize } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
class QueueProtocol implements IMessagePassingProtocol {
|
||||
|
||||
@@ -111,6 +113,8 @@ interface ITestService {
|
||||
|
||||
class TestService implements ITestService {
|
||||
|
||||
private disposables = new DisposableStore();
|
||||
|
||||
private readonly _onPong = new Emitter<string>();
|
||||
readonly onPong = this._onPong.event;
|
||||
|
||||
@@ -131,7 +135,7 @@ class TestService implements ITestService {
|
||||
return Promise.reject(canceled());
|
||||
}
|
||||
|
||||
return new Promise((_, e) => cancellationToken.onCancellationRequested(() => e(canceled())));
|
||||
return new Promise((_, e) => this.disposables.add(cancellationToken.onCancellationRequested(() => e(canceled()))));
|
||||
}
|
||||
|
||||
buffersLength(buffers: VSBuffer[]): Promise<number> {
|
||||
@@ -149,6 +153,10 @@ class TestService implements ITestService {
|
||||
context(context?: unknown): Promise<unknown> {
|
||||
return Promise.resolve(context);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.disposables.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class TestChannel implements IServerChannel {
|
||||
@@ -213,6 +221,8 @@ class TestChannelClient implements ITestService {
|
||||
|
||||
suite('Base IPC', function () {
|
||||
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
test('createProtocolPair', async function () {
|
||||
const [clientProtocol, serverProtocol] = createProtocolPair();
|
||||
|
||||
@@ -236,21 +246,16 @@ suite('Base IPC', function () {
|
||||
let ipcService: ITestService;
|
||||
|
||||
setup(function () {
|
||||
service = new TestService();
|
||||
const testServer = new TestIPCServer();
|
||||
service = store.add(new TestService());
|
||||
const testServer = store.add(new TestIPCServer());
|
||||
server = testServer;
|
||||
|
||||
server.registerChannel(TestChannelId, new TestChannel(service));
|
||||
|
||||
client = testServer.createConnection('client1');
|
||||
client = store.add(testServer.createConnection('client1'));
|
||||
ipcService = new TestChannelClient(client.getChannel(TestChannelId));
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
client.dispose();
|
||||
server.dispose();
|
||||
});
|
||||
|
||||
test('call success', async function () {
|
||||
const r = await ipcService.marco();
|
||||
return assert.strictEqual(r, 'polo');
|
||||
@@ -301,7 +306,7 @@ suite('Base IPC', function () {
|
||||
test('listen to events', async function () {
|
||||
const messages: string[] = [];
|
||||
|
||||
ipcService.onPong(msg => messages.push(msg));
|
||||
store.add(ipcService.onPong(msg => messages.push(msg)));
|
||||
await timeout(0);
|
||||
|
||||
assert.deepStrictEqual(messages, []);
|
||||
@@ -343,20 +348,21 @@ suite('Base IPC', function () {
|
||||
let service: TestService;
|
||||
let ipcService: ITestService;
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
setup(function () {
|
||||
service = new TestService();
|
||||
const testServer = new TestIPCServer();
|
||||
service = store.add(new TestService());
|
||||
const testServer = disposables.add(new TestIPCServer());
|
||||
server = testServer;
|
||||
|
||||
server.registerChannel(TestChannelId, ProxyChannel.fromService(service));
|
||||
server.registerChannel(TestChannelId, ProxyChannel.fromService(service, disposables));
|
||||
|
||||
client = testServer.createConnection('client1');
|
||||
client = disposables.add(testServer.createConnection('client1'));
|
||||
ipcService = ProxyChannel.toService(client.getChannel(TestChannelId));
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
client.dispose();
|
||||
server.dispose();
|
||||
disposables.clear();
|
||||
});
|
||||
|
||||
test('call success', async function () {
|
||||
@@ -376,7 +382,7 @@ suite('Base IPC', function () {
|
||||
test('listen to events', async function () {
|
||||
const messages: string[] = [];
|
||||
|
||||
ipcService.onPong(msg => messages.push(msg));
|
||||
disposables.add(ipcService.onPong(msg => messages.push(msg)));
|
||||
await timeout(0);
|
||||
|
||||
assert.deepStrictEqual(messages, []);
|
||||
@@ -409,20 +415,21 @@ suite('Base IPC', function () {
|
||||
let service: TestService;
|
||||
let ipcService: ITestService;
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
setup(function () {
|
||||
service = new TestService();
|
||||
const testServer = new TestIPCServer();
|
||||
service = store.add(new TestService());
|
||||
const testServer = disposables.add(new TestIPCServer());
|
||||
server = testServer;
|
||||
|
||||
server.registerChannel(TestChannelId, ProxyChannel.fromService(service));
|
||||
server.registerChannel(TestChannelId, ProxyChannel.fromService(service, disposables));
|
||||
|
||||
client = testServer.createConnection('client1');
|
||||
client = disposables.add(testServer.createConnection('client1'));
|
||||
ipcService = ProxyChannel.toService(client.getChannel(TestChannelId), { context: 'Super Context' });
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
client.dispose();
|
||||
server.dispose();
|
||||
disposables.clear();
|
||||
});
|
||||
|
||||
test('call extra context', async function () {
|
||||
@@ -433,20 +440,20 @@ suite('Base IPC', function () {
|
||||
|
||||
suite('one to many', function () {
|
||||
test('all clients get pinged', async function () {
|
||||
const service = new TestService();
|
||||
const service = store.add(new TestService());
|
||||
const channel = new TestChannel(service);
|
||||
const server = new TestIPCServer();
|
||||
const server = store.add(new TestIPCServer());
|
||||
server.registerChannel('channel', channel);
|
||||
|
||||
let client1GotPinged = false;
|
||||
const client1 = server.createConnection('client1');
|
||||
const client1 = store.add(server.createConnection('client1'));
|
||||
const ipcService1 = new TestChannelClient(client1.getChannel('channel'));
|
||||
ipcService1.onPong(() => client1GotPinged = true);
|
||||
store.add(ipcService1.onPong(() => client1GotPinged = true));
|
||||
|
||||
let client2GotPinged = false;
|
||||
const client2 = server.createConnection('client2');
|
||||
const client2 = store.add(server.createConnection('client2'));
|
||||
const ipcService2 = new TestChannelClient(client2.getChannel('channel'));
|
||||
ipcService2.onPong(() => client2GotPinged = true);
|
||||
store.add(ipcService2.onPong(() => client2GotPinged = true));
|
||||
|
||||
await timeout(1);
|
||||
service.ping('hello');
|
||||
@@ -454,24 +461,20 @@ suite('Base IPC', function () {
|
||||
await timeout(1);
|
||||
assert(client1GotPinged, 'client 1 got pinged');
|
||||
assert(client2GotPinged, 'client 2 got pinged');
|
||||
|
||||
client1.dispose();
|
||||
client2.dispose();
|
||||
server.dispose();
|
||||
});
|
||||
|
||||
test('server gets pings from all clients (broadcast channel)', async function () {
|
||||
const server = new TestIPCServer();
|
||||
const server = store.add(new TestIPCServer());
|
||||
|
||||
const client1 = server.createConnection('client1');
|
||||
const clientService1 = new TestService();
|
||||
const clientService1 = store.add(new TestService());
|
||||
const clientChannel1 = new TestChannel(clientService1);
|
||||
client1.registerChannel('channel', clientChannel1);
|
||||
|
||||
const pings: string[] = [];
|
||||
const channel = server.getChannel('channel', () => true);
|
||||
const service = new TestChannelClient(channel);
|
||||
service.onPong(msg => pings.push(msg));
|
||||
store.add(service.onPong(msg => pings.push(msg)));
|
||||
|
||||
await timeout(1);
|
||||
clientService1.ping('hello 1');
|
||||
@@ -480,7 +483,7 @@ suite('Base IPC', function () {
|
||||
assert.deepStrictEqual(pings, ['hello 1']);
|
||||
|
||||
const client2 = server.createConnection('client2');
|
||||
const clientService2 = new TestService();
|
||||
const clientService2 = store.add(new TestService());
|
||||
const clientChannel2 = new TestChannel(clientService2);
|
||||
client2.registerChannel('channel', clientChannel2);
|
||||
|
||||
@@ -503,7 +506,6 @@ suite('Base IPC', function () {
|
||||
assert.deepStrictEqual(pings, ['hello 1', 'hello 2', 'hello again 2']);
|
||||
|
||||
client2.dispose();
|
||||
server.dispose();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@ import { isEqualOrParent } from 'vs/base/common/extpath';
|
||||
import { once } from 'vs/base/common/functional';
|
||||
import { stripComments } from 'vs/base/common/json';
|
||||
import { getPathLabel } from 'vs/base/common/labels';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isAbsolute, join, posix } from 'vs/base/common/path';
|
||||
import { IProcessEnvironment, isLinux, isLinuxSnap, isMacintosh, isWindows, OS } from 'vs/base/common/platform';
|
||||
@@ -1051,10 +1051,12 @@ export class CodeApplication extends Disposable {
|
||||
// can talk to the first instance. Electron IPC does not work
|
||||
// across apps until `requestSingleInstance` APIs are adopted.
|
||||
|
||||
const launchChannel = ProxyChannel.fromService(accessor.get(ILaunchMainService), { disableMarshalling: true });
|
||||
const disposables = this._register(new DisposableStore());
|
||||
|
||||
const launchChannel = ProxyChannel.fromService(accessor.get(ILaunchMainService), disposables, { disableMarshalling: true });
|
||||
this.mainProcessNodeIpcServer.registerChannel('launch', launchChannel);
|
||||
|
||||
const diagnosticsChannel = ProxyChannel.fromService(accessor.get(IDiagnosticsMainService), { disableMarshalling: true });
|
||||
const diagnosticsChannel = ProxyChannel.fromService(accessor.get(IDiagnosticsMainService), disposables, { disableMarshalling: true });
|
||||
this.mainProcessNodeIpcServer.registerChannel('diagnostics', diagnosticsChannel);
|
||||
|
||||
// Policies (main & shared process)
|
||||
@@ -1070,7 +1072,7 @@ export class CodeApplication extends Disposable {
|
||||
sharedProcessClient.then(client => client.registerChannel(LOCAL_FILE_SYSTEM_CHANNEL_NAME, fileSystemProviderChannel));
|
||||
|
||||
// User Data Profiles
|
||||
const userDataProfilesService = ProxyChannel.fromService(accessor.get(IUserDataProfilesMainService));
|
||||
const userDataProfilesService = ProxyChannel.fromService(accessor.get(IUserDataProfilesMainService), disposables);
|
||||
mainProcessElectronServer.registerChannel('userDataProfiles', userDataProfilesService);
|
||||
sharedProcessClient.then(client => client.registerChannel('userDataProfiles', userDataProfilesService));
|
||||
|
||||
@@ -1083,45 +1085,45 @@ export class CodeApplication extends Disposable {
|
||||
mainProcessElectronServer.registerChannel('update', updateChannel);
|
||||
|
||||
// Issues
|
||||
const issueChannel = ProxyChannel.fromService(accessor.get(IIssueMainService));
|
||||
const issueChannel = ProxyChannel.fromService(accessor.get(IIssueMainService), disposables);
|
||||
mainProcessElectronServer.registerChannel('issue', issueChannel);
|
||||
|
||||
// Encryption
|
||||
const encryptionChannel = ProxyChannel.fromService(accessor.get(IEncryptionMainService));
|
||||
const encryptionChannel = ProxyChannel.fromService(accessor.get(IEncryptionMainService), disposables);
|
||||
mainProcessElectronServer.registerChannel('encryption', encryptionChannel);
|
||||
|
||||
// Signing
|
||||
const signChannel = ProxyChannel.fromService(accessor.get(ISignService));
|
||||
const signChannel = ProxyChannel.fromService(accessor.get(ISignService), disposables);
|
||||
mainProcessElectronServer.registerChannel('sign', signChannel);
|
||||
|
||||
// Keyboard Layout
|
||||
const keyboardLayoutChannel = ProxyChannel.fromService(accessor.get(IKeyboardLayoutMainService));
|
||||
const keyboardLayoutChannel = ProxyChannel.fromService(accessor.get(IKeyboardLayoutMainService), disposables);
|
||||
mainProcessElectronServer.registerChannel('keyboardLayout', keyboardLayoutChannel);
|
||||
|
||||
// Native host (main & shared process)
|
||||
this.nativeHostMainService = accessor.get(INativeHostMainService);
|
||||
const nativeHostChannel = ProxyChannel.fromService(this.nativeHostMainService);
|
||||
const nativeHostChannel = ProxyChannel.fromService(this.nativeHostMainService, disposables);
|
||||
mainProcessElectronServer.registerChannel('nativeHost', nativeHostChannel);
|
||||
sharedProcessClient.then(client => client.registerChannel('nativeHost', nativeHostChannel));
|
||||
|
||||
// Workspaces
|
||||
const workspacesChannel = ProxyChannel.fromService(accessor.get(IWorkspacesService));
|
||||
const workspacesChannel = ProxyChannel.fromService(accessor.get(IWorkspacesService), disposables);
|
||||
mainProcessElectronServer.registerChannel('workspaces', workspacesChannel);
|
||||
|
||||
// Menubar
|
||||
const menubarChannel = ProxyChannel.fromService(accessor.get(IMenubarMainService));
|
||||
const menubarChannel = ProxyChannel.fromService(accessor.get(IMenubarMainService), disposables);
|
||||
mainProcessElectronServer.registerChannel('menubar', menubarChannel);
|
||||
|
||||
// URL handling
|
||||
const urlChannel = ProxyChannel.fromService(accessor.get(IURLService));
|
||||
const urlChannel = ProxyChannel.fromService(accessor.get(IURLService), disposables);
|
||||
mainProcessElectronServer.registerChannel('url', urlChannel);
|
||||
|
||||
// Extension URL Trust
|
||||
const extensionUrlTrustChannel = ProxyChannel.fromService(accessor.get(IExtensionUrlTrustService));
|
||||
const extensionUrlTrustChannel = ProxyChannel.fromService(accessor.get(IExtensionUrlTrustService), disposables);
|
||||
mainProcessElectronServer.registerChannel('extensionUrlTrust', extensionUrlTrustChannel);
|
||||
|
||||
// Webview Manager
|
||||
const webviewChannel = ProxyChannel.fromService(accessor.get(IWebviewManagerService));
|
||||
const webviewChannel = ProxyChannel.fromService(accessor.get(IWebviewManagerService), disposables);
|
||||
mainProcessElectronServer.registerChannel('webview', webviewChannel);
|
||||
|
||||
// Storage (main & shared process)
|
||||
@@ -1134,11 +1136,11 @@ export class CodeApplication extends Disposable {
|
||||
sharedProcessClient.then(client => client.registerChannel('profileStorageListener', profileStorageListener));
|
||||
|
||||
// Terminal
|
||||
const ptyHostChannel = ProxyChannel.fromService(accessor.get(ILocalPtyService));
|
||||
const ptyHostChannel = ProxyChannel.fromService(accessor.get(ILocalPtyService), disposables);
|
||||
mainProcessElectronServer.registerChannel(TerminalIpcChannels.LocalPty, ptyHostChannel);
|
||||
|
||||
// External Terminal
|
||||
const externalTerminalChannel = ProxyChannel.fromService(accessor.get(IExternalTerminalMainService));
|
||||
const externalTerminalChannel = ProxyChannel.fromService(accessor.get(IExternalTerminalMainService), disposables);
|
||||
mainProcessElectronServer.registerChannel('externalTerminal', externalTerminalChannel);
|
||||
|
||||
// Logger
|
||||
@@ -1151,11 +1153,11 @@ export class CodeApplication extends Disposable {
|
||||
mainProcessElectronServer.registerChannel('extensionhostdebugservice', electronExtensionHostDebugBroadcastChannel);
|
||||
|
||||
// Extension Host Starter
|
||||
const extensionHostStarterChannel = ProxyChannel.fromService(accessor.get(IExtensionHostStarter));
|
||||
const extensionHostStarterChannel = ProxyChannel.fromService(accessor.get(IExtensionHostStarter), disposables);
|
||||
mainProcessElectronServer.registerChannel(ipcExtensionHostStarterChannelName, extensionHostStarterChannel);
|
||||
|
||||
// Utility Process Worker
|
||||
const utilityProcessWorkerChannel = ProxyChannel.fromService(accessor.get(IUtilityProcessWorkerMainService));
|
||||
const utilityProcessWorkerChannel = ProxyChannel.fromService(accessor.get(IUtilityProcessWorkerMainService), disposables);
|
||||
mainProcessElectronServer.registerChannel(ipcUtilityProcessWorkerChannelName, utilityProcessWorkerChannel);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { hostname, release } from 'os';
|
||||
import { MessagePortMain, MessageEvent } from 'vs/base/parts/sandbox/node/electronTypes';
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors';
|
||||
import { combinedDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { combinedDisposable, Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { firstOrDefault } from 'vs/base/common/arrays';
|
||||
@@ -367,16 +367,18 @@ class SharedProcessMain extends Disposable implements IClientConnectionFilter {
|
||||
|
||||
private initChannels(accessor: ServicesAccessor): void {
|
||||
|
||||
const disposables = this._register(new DisposableStore());
|
||||
|
||||
// Extensions Management
|
||||
const channel = new ExtensionManagementChannel(accessor.get(IExtensionManagementService), () => null);
|
||||
this.server.registerChannel('extensions', channel);
|
||||
|
||||
// Language Packs
|
||||
const languagePacksChannel = ProxyChannel.fromService(accessor.get(ILanguagePackService));
|
||||
const languagePacksChannel = ProxyChannel.fromService(accessor.get(ILanguagePackService), disposables);
|
||||
this.server.registerChannel('languagePacks', languagePacksChannel);
|
||||
|
||||
// Diagnostics
|
||||
const diagnosticsChannel = ProxyChannel.fromService(accessor.get(IDiagnosticsService));
|
||||
const diagnosticsChannel = ProxyChannel.fromService(accessor.get(IDiagnosticsService), disposables);
|
||||
this.server.registerChannel('diagnostics', diagnosticsChannel);
|
||||
|
||||
// Extension Tips
|
||||
@@ -384,11 +386,11 @@ class SharedProcessMain extends Disposable implements IClientConnectionFilter {
|
||||
this.server.registerChannel('extensionTipsService', extensionTipsChannel);
|
||||
|
||||
// Checksum
|
||||
const checksumChannel = ProxyChannel.fromService(accessor.get(IChecksumService));
|
||||
const checksumChannel = ProxyChannel.fromService(accessor.get(IChecksumService), disposables);
|
||||
this.server.registerChannel('checksum', checksumChannel);
|
||||
|
||||
// Profiling
|
||||
const profilingChannel = ProxyChannel.fromService(accessor.get(IV8InspectProfilingService));
|
||||
const profilingChannel = ProxyChannel.fromService(accessor.get(IV8InspectProfilingService), disposables);
|
||||
this.server.registerChannel('v8InspectProfiling', profilingChannel);
|
||||
|
||||
// Settings Sync
|
||||
@@ -396,7 +398,7 @@ class SharedProcessMain extends Disposable implements IClientConnectionFilter {
|
||||
this.server.registerChannel('userDataSyncMachines', userDataSyncMachineChannel);
|
||||
|
||||
// Custom Endpoint Telemetry
|
||||
const customEndpointTelemetryChannel = ProxyChannel.fromService(accessor.get(ICustomEndpointTelemetryService));
|
||||
const customEndpointTelemetryChannel = ProxyChannel.fromService(accessor.get(ICustomEndpointTelemetryService), disposables);
|
||||
this.server.registerChannel('customEndpointTelemetry', customEndpointTelemetryChannel);
|
||||
|
||||
const userDataSyncAccountChannel = new UserDataSyncAccountServiceChannel(accessor.get(IUserDataSyncAccountService));
|
||||
@@ -413,11 +415,11 @@ class SharedProcessMain extends Disposable implements IClientConnectionFilter {
|
||||
this.server.registerChannel('userDataAutoSync', userDataAutoSyncChannel);
|
||||
|
||||
// Tunnel
|
||||
const sharedProcessTunnelChannel = ProxyChannel.fromService(accessor.get(ISharedProcessTunnelService));
|
||||
const sharedProcessTunnelChannel = ProxyChannel.fromService(accessor.get(ISharedProcessTunnelService), disposables);
|
||||
this.server.registerChannel(ipcSharedProcessTunnelChannelName, sharedProcessTunnelChannel);
|
||||
|
||||
// Remote Tunnel
|
||||
const remoteTunnelChannel = ProxyChannel.fromService(accessor.get(IRemoteTunnelService));
|
||||
const remoteTunnelChannel = ProxyChannel.fromService(accessor.get(IRemoteTunnelService), disposables);
|
||||
this.server.registerChannel('remoteTunnel', remoteTunnelChannel);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { Server as ChildProcessServer } from 'vs/base/parts/ipc/node/ipc.cp';
|
||||
import { Server as UtilityProcessServer } from 'vs/base/parts/ipc/node/ipc.mp';
|
||||
@@ -17,4 +18,4 @@ if (isUtilityProcess(process)) {
|
||||
}
|
||||
|
||||
const service = new UniversalWatcher();
|
||||
server.registerChannel('watcher', ProxyChannel.fromService(service));
|
||||
server.registerChannel('watcher', ProxyChannel.fromService(service, new DisposableStore()));
|
||||
|
||||
@@ -21,6 +21,7 @@ import { HeartbeatService } from 'vs/platform/terminal/node/heartbeatService';
|
||||
import { PtyService } from 'vs/platform/terminal/node/ptyService';
|
||||
import { isUtilityProcess } from 'vs/base/parts/sandbox/node/electronTypes';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
|
||||
startPtyHost();
|
||||
|
||||
@@ -72,13 +73,15 @@ async function startPtyHost() {
|
||||
logService.warn(`Pty host is simulating ${simulatedLatency}ms latency`);
|
||||
}
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
// Heartbeat responsiveness tracking
|
||||
const heartbeatService = new HeartbeatService();
|
||||
server.registerChannel(TerminalIpcChannels.Heartbeat, ProxyChannel.fromService(heartbeatService));
|
||||
server.registerChannel(TerminalIpcChannels.Heartbeat, ProxyChannel.fromService(heartbeatService, disposables));
|
||||
|
||||
// Init pty service
|
||||
const ptyService = new PtyService(logService, productService, reconnectConstants, simulatedLatency);
|
||||
const ptyServiceChannel = ProxyChannel.fromService(ptyService);
|
||||
const ptyServiceChannel = ProxyChannel.fromService(ptyService, disposables);
|
||||
server.registerChannel(TerminalIpcChannels.PtyHost, ptyServiceChannel);
|
||||
|
||||
// Register a channel for direct communication via Message Port
|
||||
|
||||
Reference in New Issue
Block a user