From 9511e8c7252683569ecfa13373a2a130f14515d9 Mon Sep 17 00:00:00 2001 From: Andy Jordan Date: Mon, 21 Nov 2022 12:59:52 -0800 Subject: [PATCH 1/2] Add lock to `Logger.WriteLine` since it's not re-entrant Hence we were losing logs. --- src/logging.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/logging.ts b/src/logging.ts index ef280cf8d8..d136609de0 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -35,6 +35,7 @@ export class Logger implements ILogger { private logChannel: vscode.OutputChannel; private logFilePath: vscode.Uri; private logDirectoryCreated = false; + private writingLog = false; constructor(logLevelName: string, globalStorageUri: vscode.Uri) { this.logLevel = Logger.logLevelNameToValue(logLevelName); @@ -194,11 +195,16 @@ export class Logger implements ILogger { const timestampedMessage = Logger.timestampMessage(message, level); this.logChannel.appendLine(timestampedMessage); if (this.logLevel !== LogLevel.None) { + // A simple lock because this function isn't re-entrant. + while (this.writingLog) { + await utils.sleep(300); + } try { + this.writingLog = true; if (!this.logDirectoryCreated) { this.logChannel.appendLine(Logger.timestampMessage(`Creating log directory at: '${this.logDirectoryPath}'`, level)); await vscode.workspace.fs.createDirectory(this.logDirectoryPath); - this.logDirectoryCreated = await utils.checkIfDirectoryExists(this.logDirectoryPath); + this.logDirectoryCreated = true; } let log = new Uint8Array(); if (await utils.checkIfFileExists(this.logFilePath)) { @@ -209,6 +215,8 @@ export class Logger implements ILogger { Buffer.concat([log, Buffer.from(timestampedMessage)])); } catch (e) { console.log(`Error writing to vscode-powershell log file: ${e}`); + } finally { + this.writingLog = false; } } } From 40d6d4bf6ac20aea5ec979770b7295200afcd452 Mon Sep 17 00:00:00 2001 From: Andy Jordan Date: Mon, 21 Nov 2022 13:22:00 -0800 Subject: [PATCH 2/2] Fix session and log directories when user folder is on UNC share When we moved to using `globalStorageUri` and passing `vscode.Uri`s around, we did not test UNC shares. It turns out that while `vscode.Uri.fsPath`'s documentation says that it "does not look at scheme," it actually does look at the scheme and essentially requires it to be `file`. The scheme of the `globalStorageUri` however is `vscode-userdata`, so the `fsPath` fails to then handle the UNC share path. We are now replacing the scheme with `file` to get around this bug. --- src/features/ExternalApi.ts | 4 +++- src/logging.ts | 4 +++- src/session.ts | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/features/ExternalApi.ts b/src/features/ExternalApi.ts index 686ac643bf..8c2f0af25b 100644 --- a/src/features/ExternalApi.ts +++ b/src/features/ExternalApi.ts @@ -169,7 +169,9 @@ export class ExternalApiFeature extends LanguageClientConsumer implements IPower } public getStorageUri(): vscode.Uri { - return this.extensionContext.globalStorageUri; + // We have to override the scheme because it defaults to + // 'vscode-userdata' which breaks UNC paths. + return this.extensionContext.globalStorageUri.with({ scheme: "file"}); } public dispose() { diff --git a/src/logging.ts b/src/logging.ts index d136609de0..fd33a303b2 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -40,8 +40,10 @@ export class Logger implements ILogger { constructor(logLevelName: string, globalStorageUri: vscode.Uri) { this.logLevel = Logger.logLevelNameToValue(logLevelName); this.logChannel = vscode.window.createOutputChannel("PowerShell Extension Logs"); + // We have to override the scheme because it defaults to + // 'vscode-userdata' which breaks UNC paths. this.logDirectoryPath = vscode.Uri.joinPath( - globalStorageUri, + globalStorageUri.with({ scheme: "file" }), "logs", `${Math.floor(Date.now() / 1000)}-${vscode.env.sessionId}`); this.logFilePath = this.getLogFilePath("vscode-powershell"); diff --git a/src/session.ts b/src/session.ts index 97b8d05c6d..650a526c52 100644 --- a/src/session.ts +++ b/src/session.ts @@ -111,7 +111,9 @@ export class SessionManager implements Middleware { // Create the language status item this.languageStatusItem = this.createStatusBarItem(); - this.sessionsFolder = vscode.Uri.joinPath(extensionContext.globalStorageUri, "sessions"); + // We have to override the scheme because it defaults to + // 'vscode-userdata' which breaks UNC paths. + this.sessionsFolder = vscode.Uri.joinPath(extensionContext.globalStorageUri.with({ scheme: "file"}), "sessions"); this.platformDetails = getPlatformDetails(); this.HostName = hostName; this.HostVersion = hostVersion;