Skip to content

Commit c55d6aa

Browse files
committed
Lock SessionManager.start() so only one session is started
Also correctly wait for disposal on extension deactivation, and more carefully dispose and set to undefined in `SessionManager.dispose()`.
1 parent 1c14527 commit c55d6aa

File tree

2 files changed

+48
-24
lines changed

2 files changed

+48
-24
lines changed

src/main.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<IPower
181181
};
182182
}
183183

184-
export function deactivate(): void {
184+
export async function deactivate(): Promise<void> {
185185
// Clean up all extension features
186186
for (const languageClientConsumer of languageClientConsumers) {
187187
languageClientConsumer.dispose();
@@ -192,11 +192,11 @@ export function deactivate(): void {
192192
};
193193

194194
// Dispose of the current session
195-
sessionManager.dispose();
195+
await sessionManager.dispose();
196196

197197
// Dispose of the logger
198198
logger.dispose();
199199

200200
// Dispose of telemetry reporter
201-
telemetryReporter.dispose();
201+
await telemetryReporter.dispose();
202202
}

src/session.ts

+45-21
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export class SessionManager implements Middleware {
103103
private sessionDetails: IEditorServicesSessionDetails;
104104
private sessionsFolder: vscode.Uri;
105105
private bundledModulesPath: string;
106+
private starting: boolean = false;
106107
private started: boolean = false;
107108

108109
// Initialized by the start() method, since this requires settings
@@ -160,6 +161,19 @@ export class SessionManager implements Middleware {
160161
}
161162

162163
public async start(exeNameOverride?: string) {
164+
// A simple lock because this function isn't re-entrant.
165+
if (this.started || this.starting) {
166+
return await this.waitUntilStarted();
167+
}
168+
try {
169+
this.starting = true;
170+
await this._start(exeNameOverride);
171+
} finally {
172+
this.starting = false;
173+
}
174+
}
175+
176+
private async _start(exeNameOverride?: string) {
163177
await Settings.validateCwdSetting();
164178
this.sessionSettings = Settings.load();
165179

@@ -275,31 +289,41 @@ Type 'help' to get help.
275289
public async stop() {
276290
this.log.write("Shutting down language client...");
277291

278-
if (this.sessionStatus === SessionStatus.Failed) {
279-
// Before moving further, clear out the client and process if
280-
// the process is already dead (i.e. it crashed).
281-
this.languageClient = undefined;
282-
this.languageServerProcess = undefined;
283-
}
292+
try {
293+
if (this.sessionStatus === SessionStatus.Failed) {
294+
// Before moving further, clear out the client and process if
295+
// the process is already dead (i.e. it crashed).
296+
this.languageClient.dispose();
297+
this.languageClient = undefined;
298+
this.languageServerProcess.dispose();
299+
this.languageServerProcess = undefined;
300+
}
284301

285-
this.sessionStatus = SessionStatus.Stopping;
302+
this.sessionStatus = SessionStatus.Stopping;
286303

287-
// Stop the language client.
288-
if (this.languageClient !== undefined) {
289-
await this.languageClient.stop();
290-
this.languageClient = undefined;
291-
}
304+
// Stop the language client.
305+
if (this.languageClient !== undefined) {
306+
await this.languageClient.stop();
307+
this.languageClient.dispose();
308+
this.languageClient = undefined;
309+
}
292310

293-
// Kill the PowerShell process(es) we spawned.
294-
if (this.debugSessionProcess) {
295-
this.debugSessionProcess.dispose();
296-
this.debugEventHandler.dispose();
297-
}
298-
if (this.languageServerProcess) {
299-
this.languageServerProcess.dispose();
300-
}
311+
// Kill the PowerShell process(es) we spawned.
312+
if (this.debugSessionProcess) {
313+
this.debugSessionProcess.dispose();
314+
this.debugSessionProcess = undefined;
315+
this.debugEventHandler.dispose();
316+
this.debugEventHandler = undefined;
317+
}
301318

302-
this.sessionStatus = SessionStatus.NotStarted;
319+
if (this.languageServerProcess) {
320+
this.languageServerProcess.dispose();
321+
this.languageServerProcess = undefined;
322+
}
323+
} finally {
324+
this.sessionStatus = SessionStatus.NotStarted;
325+
this.started = false;
326+
}
303327
}
304328

305329
public async restartSession(exeNameOverride?: string) {

0 commit comments

Comments
 (0)