Don't terminate extension host on a timeout

We will clean it up on our end if necessary. This allows reconnections
after any length of time.
This commit is contained in:
Asher 2019-09-13 10:48:04 -05:00
parent 48a97abe1d
commit 1bd5eca73d
No known key found for this signature in database
GPG Key ID: D63C1EF81242354A
3 changed files with 35 additions and 44 deletions

View File

@ -1032,37 +1032,18 @@ index 7c3b6ae53e..18dec6effa 100644
get webviewResourceRoot(): string { get webviewResourceRoot(): string {
diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts
index 6d31b177ac..a586ac7466 100644 index 6d31b177ac..d7c1705c57 100644
--- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts --- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts
+++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts
@@ -116,7 +116,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> { @@ -128,7 +128,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
protocol.onClose(() => onTerminate()); } else {
resolve(protocol); // Do not wait for web companion to reconnect
- if (msg.skipWebSocketFrames) {
+ // if (msg.skipWebSocketFrames) {
// Wait for rich client to reconnect
protocol.onSocketClose(() => { protocol.onSocketClose(() => {
// The socket has closed, let's give the renderer a certain amount of time to reconnect
@@ -125,12 +125,12 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
onTerminate();
}, ProtocolConstants.ReconnectionGraceTime);
});
- } else {
- // Do not wait for web companion to reconnect
- protocol.onSocketClose(() => {
- onTerminate(); - onTerminate();
- }); + process.send!('VSCODE_EXTHOST_DISCONNECTED'); // onTerminate();
- }
+ // } else {
+ // // Do not wait for web companion to reconnect
+ // protocol.onSocketClose(() => {
+ // onTerminate();
+ // });
+ // }
}
}
}); });
}
}
diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts
index 681fc606b6..e34ef5d4bc 100644 index 681fc606b6..e34ef5d4bc 100644
--- a/src/vs/workbench/workbench.web.main.ts --- a/src/vs/workbench/workbench.web.main.ts

View File

@ -17,10 +17,7 @@ export abstract class Connection {
private disposed = false; private disposed = false;
private _offline: number | undefined; private _offline: number | undefined;
public constructor(protected protocol: Protocol) { public constructor(protected protocol: Protocol, public readonly token: string) {}
protocol.onClose(() => this.dispose()); // Explicit close.
protocol.onSocketClose(() => this._offline = Date.now()); // Might reconnect.
}
public get offline(): number | undefined { public get offline(): number | undefined {
return this._offline; return this._offline;
@ -39,6 +36,12 @@ export abstract class Connection {
} }
} }
protected setOffline(): void {
if (!this._offline) {
this._offline = Date.now();
}
}
/** /**
* Set up the connection on a new socket. * Set up the connection on a new socket.
*/ */
@ -50,6 +53,12 @@ export abstract class Connection {
* Used for all the IPC channels. * Used for all the IPC channels.
*/ */
export class ManagementConnection extends Connection { export class ManagementConnection extends Connection {
public constructor(protected protocol: Protocol, token: string) {
super(protocol, token);
protocol.onClose(() => this.dispose()); // Explicit close.
protocol.onSocketClose(() => this.setOffline()); // Might reconnect.
}
protected doDispose(): void { protected doDispose(): void {
this.protocol.sendDisconnect(); this.protocol.sendDisconnect();
this.protocol.dispose(); this.protocol.dispose();
@ -66,11 +75,11 @@ export class ExtensionHostConnection extends Connection {
private process?: cp.ChildProcess; private process?: cp.ChildProcess;
public constructor( public constructor(
locale:string, protocol: Protocol, buffer: VSBuffer, locale:string, protocol: Protocol, buffer: VSBuffer, token: string,
private readonly log: ILogService, private readonly log: ILogService,
private readonly environment: IEnvironmentService, private readonly environment: IEnvironmentService,
) { ) {
super(protocol); super(protocol, token);
this.protocol.dispose(); this.protocol.dispose();
this.spawn(locale, buffer).then((p) => this.process = p); this.spawn(locale, buffer).then((p) => this.process = p);
this.protocol.getUnderlyingSocket().pause(); this.protocol.getUnderlyingSocket().pause();
@ -129,6 +138,9 @@ export class ExtensionHostConnection extends Connection {
const severity = (<any>this.log)[event.severity] ? event.severity : "info"; const severity = (<any>this.log)[event.severity] ? event.severity : "info";
(<any>this.log)[severity]("Extension host", event.arguments); (<any>this.log)[severity]("Extension host", event.arguments);
} }
if (event && event.type === "VSCODE_EXTHOST_DISCONNECTED") {
this.setOffline();
}
}); });
const listen = (message: IExtHostReadyMessage) => { const listen = (message: IExtHostReadyMessage) => {

View File

@ -449,7 +449,7 @@ export class MainServer extends Server {
public readonly onDidClientConnect = this._onDidClientConnect.event; public readonly onDidClientConnect = this._onDidClientConnect.event;
private readonly ipc = new IPCServer(this.onDidClientConnect); private readonly ipc = new IPCServer(this.onDidClientConnect);
private readonly maxOfflineConnections = 5; private readonly maxExtraOfflineConnections = 0;
private readonly connections = new Map<ConnectionType, Map<string, Connection>>(); private readonly connections = new Map<ConnectionType, Map<string, Connection>>();
private readonly services = new ServiceCollection(); private readonly services = new ServiceCollection();
@ -601,7 +601,7 @@ export class MainServer extends Server {
let connection: Connection; let connection: Connection;
if (message.desiredConnectionType === ConnectionType.Management) { if (message.desiredConnectionType === ConnectionType.Management) {
connection = new ManagementConnection(protocol); connection = new ManagementConnection(protocol, token);
this._onDidClientConnect.fire({ this._onDidClientConnect.fire({
protocol, onDidClientDisconnect: connection.onClose, protocol, onDidClientDisconnect: connection.onClose,
}); });
@ -609,28 +609,26 @@ export class MainServer extends Server {
const buffer = protocol.readEntireBuffer(); const buffer = protocol.readEntireBuffer();
connection = new ExtensionHostConnection( connection = new ExtensionHostConnection(
message.args ? message.args.language : "en", message.args ? message.args.language : "en",
protocol, buffer, protocol, buffer, token,
this.services.get(ILogService) as ILogService, this.services.get(ILogService) as ILogService,
this.services.get(IEnvironmentService) as IEnvironmentService, this.services.get(IEnvironmentService) as IEnvironmentService,
); );
} }
connections.set(token, connection); connections.set(token, connection);
this.disposeOldOfflineConnections();
connection.onClose(() => connections.delete(token)); connection.onClose(() => connections.delete(token));
this.disposeOldOfflineConnections(connections);
break; break;
case ConnectionType.Tunnel: return protocol.tunnel(); case ConnectionType.Tunnel: return protocol.tunnel();
default: throw new Error("Unrecognized connection type"); default: throw new Error("Unrecognized connection type");
} }
} }
private disposeOldOfflineConnections(): void { private disposeOldOfflineConnections(connections: Map<string, Connection>): void {
this.connections.forEach((connections) => {
const offline = Array.from(connections.values()) const offline = Array.from(connections.values())
.filter((connection) => typeof connection.offline !== "undefined"); .filter((connection) => typeof connection.offline !== "undefined");
for (let i = 0, max = offline.length - this.maxOfflineConnections; i < max; ++i) { for (let i = 0, max = offline.length - this.maxExtraOfflineConnections; i < max; ++i) {
offline[i].dispose(); offline[i].dispose();
} }
});
} }
private async initializeServices(args: ParsedArgs): Promise<void> { private async initializeServices(args: ParsedArgs): Promise<void> {