Skip to content

Commit 1164801

Browse files
committed
Keep a maximum number of connections instead of a timeout
There's no way to actually know if those clients have gone away, so it seems it might be better to base it on whether the user has connected again with new clients to determine if the old clients are now invalid.
1 parent 12e6084 commit 1164801

File tree

2 files changed

+50
-36
lines changed

2 files changed

+50
-36
lines changed

src/connection.ts

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,48 +12,54 @@ import { uriTransformerPath } from "vs/server/src/util";
1212
import { IExtHostReadyMessage } from "vs/workbench/services/extensions/common/extensionHostProtocol";
1313

1414
export abstract class Connection {
15-
protected readonly _onClose = new Emitter<void>();
15+
private readonly _onClose = new Emitter<void>();
1616
public readonly onClose = this._onClose.event;
17-
protected disposed: boolean = false;
18-
public constructor(protected protocol: Protocol) {}
17+
private disposed = false;
18+
private _offline: number | undefined;
19+
20+
public constructor(protected protocol: Protocol) {
21+
protocol.onClose(() => this.dispose()); // Explicit close.
22+
protocol.onSocketClose(() => this._offline = Date.now()); // Might reconnect.
23+
}
24+
25+
public get offline(): number | undefined {
26+
return this._offline;
27+
}
28+
29+
public reconnect(socket: ISocket, buffer: VSBuffer): void {
30+
this._offline = undefined;
31+
this.doReconnect(socket, buffer);
32+
}
33+
34+
public dispose(): void {
35+
if (!this.disposed) {
36+
this.disposed = true;
37+
this.doDispose();
38+
this._onClose.fire();
39+
}
40+
}
41+
1942
/**
2043
* Set up the connection on a new socket.
2144
*/
22-
public abstract reconnect(socket: ISocket, buffer: VSBuffer): void;
23-
protected abstract dispose(): void;
45+
protected abstract doReconnect(socket: ISocket, buffer: VSBuffer): void;
46+
protected abstract doDispose(): void;
2447
}
2548

2649
/**
2750
* Used for all the IPC channels.
2851
*/
2952
export class ManagementConnection extends Connection {
30-
private timeout: NodeJS.Timeout | undefined;
31-
private readonly wait = 1000 * 60;
32-
33-
public constructor(protocol: Protocol) {
34-
super(protocol);
35-
protocol.onClose(() => this.dispose());
36-
protocol.onSocketClose(() => {
37-
this.timeout = setTimeout(() => this.dispose(), this.wait);
38-
});
53+
protected doDispose(): void {
54+
this.protocol.sendDisconnect();
55+
this.protocol.dispose();
56+
this.protocol.getSocket().end();
3957
}
4058

41-
public reconnect(socket: ISocket, buffer: VSBuffer): void {
42-
clearTimeout(this.timeout as any); // Not sure why the type doesn't work.
59+
protected doReconnect(socket: ISocket, buffer: VSBuffer): void {
4360
this.protocol.beginAcceptReconnection(socket, buffer);
4461
this.protocol.endAcceptReconnection();
4562
}
46-
47-
protected dispose(): void {
48-
if (!this.disposed) {
49-
clearTimeout(this.timeout as any); // Not sure why the type doesn't work.
50-
this.disposed = true;
51-
this.protocol.sendDisconnect();
52-
this.protocol.dispose();
53-
this.protocol.getSocket().end();
54-
this._onClose.fire();
55-
}
56-
}
5763
}
5864

5965
export class ExtensionHostConnection extends Connection {
@@ -70,18 +76,14 @@ export class ExtensionHostConnection extends Connection {
7076
this.protocol.getUnderlyingSocket().pause();
7177
}
7278

73-
protected dispose(): void {
74-
if (!this.disposed) {
75-
this.disposed = true;
76-
if (this.process) {
77-
this.process.kill();
78-
}
79-
this.protocol.getSocket().end();
80-
this._onClose.fire();
79+
protected doDispose(): void {
80+
if (this.process) {
81+
this.process.kill();
8182
}
83+
this.protocol.getSocket().end();
8284
}
8385

84-
public reconnect(socket: ISocket, buffer: VSBuffer): void {
86+
protected doReconnect(socket: ISocket, buffer: VSBuffer): void {
8587
// This is just to set the new socket.
8688
this.protocol.beginAcceptReconnection(socket, null);
8789
this.protocol.dispose();

src/server.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ export class MainServer extends Server {
426426
public readonly onDidClientConnect = this._onDidClientConnect.event;
427427
private readonly ipc = new IPCServer(this.onDidClientConnect);
428428

429+
private readonly maxOfflineConnections = 5;
429430
private readonly connections = new Map<ConnectionType, Map<string, Connection>>();
430431

431432
private readonly services = new ServiceCollection();
@@ -586,13 +587,24 @@ export class MainServer extends Server {
586587
);
587588
}
588589
connections.set(token, connection);
590+
this.disposeOldOfflineConnections();
589591
connection.onClose(() => connections.delete(token));
590592
break;
591593
case ConnectionType.Tunnel: return protocol.tunnel();
592594
default: throw new Error("Unrecognized connection type");
593595
}
594596
}
595597

598+
private disposeOldOfflineConnections(): void {
599+
this.connections.forEach((connections) => {
600+
const offline = Array.from(connections.values())
601+
.filter((connection) => typeof connection.offline !== "undefined");
602+
for (let i = 0, max = offline.length - this.maxOfflineConnections; i < max; ++i) {
603+
offline[i].dispose();
604+
}
605+
});
606+
}
607+
596608
private async initializeServices(args: ParsedArgs): Promise<void> {
597609
const environmentService = new EnvironmentService(args, process.execPath);
598610
const logService = new SpdLogService(RemoteExtensionLogFileName, environmentService.logsPath, getLogLevel(environmentService));

0 commit comments

Comments
 (0)