dotnet / dotnet/msbuild

LoggerException occurs when trying to use the same binary logger for evaluation and build

Open
#11,867 12 comments 0 reactions 1 assignee Claimed by @SimaTian View on GitHub
Area: Logging Priority:2 triaged
Dominant language
C#
Stars
5.5k
Forks
1.5k
Avg merge
1d 8h
Merged PRs (30d)
141

Description

Context: The VS Code C# extension throws an exception when loading projects with setting `"dotnet.projects.binaryLogPath"` specified.

VS Code error log

```log
2025-05-19 10:33:59.335 [info] [Error - 10:33:59 AM] [workspace/didChangeWatchedFiles] [LanguageServerProjectLoader] Error while loading c:\Users\rigibson\src\ConsoleApp5\Program.cs: Exception thrown: Microsoft.CodeAnalysis.MSBuild.RemoteInvocationException: An exception of type Microsoft.Build.Framework.LoggerException was thrown: Failed to write to log file "C:\Users\rigibson\AppData\Local\Programs\Microsoft VS Code\binlogs\LanguageServerDesignTimeBuild-df194f26-35a6-49fa-9bc4-a895752f774e-1.binlog". The process cannot access the file 'C:\Users\rigibson\AppData\Local\Programs\Microsoft VS Code\binlogs\LanguageServerDesignTimeBuild-df194f26-35a6-49fa-9bc4-a895752f774e-1.binlog' because it is being used by another process.
at Microsoft.CodeAnalysis.MSBuild.RpcClient.InvokeCoreAsync(Int32 targetObject, String methodName, List`1 parameters, Type expectedReturnType, CancellationToken cancellationToken) in /_/src/Workspaces/MSBuild/Core/Rpc/RpcClient.cs:line 186
at Microsoft.CodeAnalysis.MSBuild.RpcClient.InvokeAsync[T](Int32 targetObject, String methodName, List`1 parameters, CancellationToken cancellationToken) in /_/src/Workspaces/MSBuild/Core/Rpc/RpcClient.cs:line 135
at Microsoft.CodeAnalysis.MSBuild.RemoteBuildHost.LoadProjectAsync(String projectFilePath, String projectContent, String languageName, CancellationToken cancellationToken) in /_/src/Workspaces/MSBuild/Core/Rpc/RemoteBuildHost.cs:line 41
at Microsoft.CodeAnalysis.LanguageServer.HostWorkspace.FileBasedProgramsProjectSystem.TryLoadProjectInMSBuildHostAsync(BuildHostProcessManager buildHostProcessManager, String documentPath, CancellationToken cancellationToken) in /_/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileBasedProgramsProjectSystem.cs:line 141
at Microsoft.CodeAnalysis.LanguageServer.HostWorkspace.LanguageServerProjectLoader.ReloadProjectAsync(ProjectToLoad projectToLoad, ToastErrorReporter toastErrorReporter, BuildHostProcessManager buildHostProcessManager, CancellationToken cancellationToken) in /_/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerProjectLoader.cs:line 208
2025-05-19 10:33:59.340 [info] [Info - 10:33:59 AM] [workspace/didChangeWatchedFiles] [LanguageServerProjectLoader] Completed (re)load of all projects in 00:00:01.1469839
2025-05-19 10:33:59.341 [info] [Debug - 10:33:59 AM] [workspace/didChangeWatchedFiles] [BuildHost PID 10208] Sending a Shutdown request to the BuildHost.
2025-05-19 10:33:59.343 [info] [Error - 10:33:59 AM] [workspace/didChangeWatchedFiles] [BuildHost PID 10208] Exception while shutting down the BuildHost process. Microsoft.CodeAnalysis.MSBuild.RemoteInvocationException: An exception of type System.InvalidOperationException was thrown: Operation is not valid due to the current state of the object.
at Microsoft.CodeAnalysis.MSBuild.RpcClient.InvokeCoreAsync(Int32 targetObject, String methodName, List`1 parameters, Type expectedReturnType, CancellationToken cancellationToken) in /_/src/Workspaces/MSBuild/Core/Rpc/RpcClient.cs:line 186
at Microsoft.CodeAnalysis.MSBuild.BuildHostProcessManager.BuildHostProcess.DisposeAsync() in /_/src/Workspaces/MSBuild/Core/MSBuild/BuildHostProcessManager.cs:line 434
2025-05-19 10:33:59.343 [info] [Error - 10:33:59 AM] [workspace/didChangeWatchedFiles]
```

What is happening is: `BinaryLogger.Initialize` is being called twice. Each time a write stream to the binlog file is opened. The second time, an IOException occurs because the first time locked the file.

Both calls to `BinaryLogger.Initialize` occur indirectly thru a single call to `ProjectBuildManager.StartBatchBuild` in Roslyn.

First call (thru ProjectBuildManager.cs#L231)

```log
Microsoft.Build.dll!Microsoft.Build.Logging.BinaryLogger.Initialize(Microsoft.Build.Framework.IEventSource eventSource) Line 79 C#
Microsoft.Build.dll!Microsoft.Build.Evaluation.ProjectCollection.ReusableLogger.Initialize(Microsoft.Build.Framework.IEventSource eventSource, int nodeCount) Line 221 C#
Microsoft.Build.dll!Microsoft.Build.BackEnd.Logging.LoggingService.InitializeLogger(Microsoft.Build.Framework.ILogger logger, Microsoft.Build.Framework.IEventSource sourceForLogger) Line 982 C#
Microsoft.Build.dll!Microsoft.Build.BackEnd.Logging.LoggingService.RegisterDistributedLogger(Microsoft.Build.Framework.ILogger centralLogger, Microsoft.Build.Logging.LoggerDescription forwardingLogger) Line 578 C#
Microsoft.Build.dll!Microsoft.Build.BackEnd.Logging.LoggingService.RegisterLogger(Microsoft.Build.Framework.ILogger logger) Line 537 C#
Microsoft.Build.dll!Microsoft.Build.Evaluation.ProjectCollection.RegisterLoggerInternal(Microsoft.Build.Framework.ILogger logger) Line 1660 C#
Microsoft.Build.dll!Microsoft.Build.Evaluation.ProjectCollection.RegisterLoggers(System.Collections.Generic.IEnumerable loggers) Line 1405 C#
Microsoft.Build.dll!Microsoft.Build.Evaluation.ProjectCollection.ProjectCollection(System.Collections.Generic.IDictionary globalProperties, System.Collections.Generic.IEnumerable loggers, System.Collections.Generic.IEnumerable remoteLoggers, Microsoft.Build.Evaluation.ToolsetDefinitionLocations toolsetDefinitionLocations, int maxNodeCount, bool onlyLogCriticalEvents, bool loadProjectsReadOnly, bool useAsynchronousLogging, bool reuseProjectRootElementCache) Line 1127 C#
Microsoft.Build.dll!Microsoft.Build.Evaluation.ProjectCollection.ProjectCollection(System.Collections.Generic.IDictionary globalProperties, System.Collections.Generic.IEnumerable loggers, System.Collections.Generic.IEnumerable remoteLoggers, Microsoft.Build.Evaluation.ToolsetDefinitionLocations toolsetDefinitionLocations, int maxNodeCount, bool onlyLogCriticalEvents, bool loadProjectsReadOnly) Line 1097 C#
Microsoft.Build.dll!Microsoft.Build.Evaluation.ProjectCollection.ProjectCollection(System.Collections.Generic.IDictionary globalProperties, System.Collections.Generic.IEnumerable loggers, System.Collections.Generic.IEnumerable remoteLoggers, Microsoft.Build.Evaluation.ToolsetDefinitionLocations toolsetDefinitionLocations, int maxNodeCount, bool onlyLogCriticalEvents) Line 1092 C#
Microsoft.Build.dll!Microsoft.Build.Evaluation.ProjectCollection.ProjectCollection(System.Collections.Generic.IDictionary globalProperties, System.Collections.Generic.IEnumerable loggers, Microsoft.Build.Evaluation.ToolsetDefinitionLocations toolsetDefinitionLocations) Line 1080 C#
Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll!Microsoft.CodeAnalysis.MSBuild.ProjectBuildManager.StartBatchBuild(System.Collections.Generic.IDictionary globalProperties) Line 231 C#
Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll!Microsoft.CodeAnalysis.MSBuild.BuildHost.CreateBuildManager() Line 122 C#
Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll!Microsoft.CodeAnalysis.MSBuild.BuildHost.LoadProjectCore(string projectFilePath, string projectContent, string languageName) Line 205 C#
Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll!Microsoft.CodeAnalysis.MSBuild.BuildHost.LoadProject(string projectFilePath, string projectContent, string languageName) Line 176 C#
```

Second call (thru ProjectBuildManager.cs#L243)

```log
Microsoft.Build.dll!Microsoft.Build.Logging.BinaryLogger.Initialize(Microsoft.Build.Framework.IEventSource eventSource) Line 79 C#
Microsoft.Build.dll!Microsoft.Build.BackEnd.Logging.LoggingService.InitializeLogger(Microsoft.Build.Framework.ILogger logger, Microsoft.Build.Framework.IEventSource sourceForLogger) Line 986 C#
Microsoft.Build.dll!Microsoft.Build.BackEnd.Logging.LoggingService.RegisterDistributedLogger(Microsoft.Build.Framework.ILogger centralLogger, Microsoft.Build.Logging.LoggerDescription forwardingLogger) Line 578 C#
Microsoft.Build.dll!Microsoft.Build.BackEnd.Logging.LoggingService.RegisterLogger(Microsoft.Build.Framework.ILogger logger) Line 537 C#
Microsoft.Build.dll!Microsoft.Build.Execution.BuildManager.CreateLoggingService(System.Collections.Generic.IEnumerable loggers, System.Collections.Generic.IEnumerable forwardingLoggers, System.Collections.Generic.ISet warningsAsErrors, System.Collections.Generic.ISet warningsNotAsErrors, System.Collections.Generic.ISet warningsAsMessages) Line 2000 C#
Microsoft.Build.dll!Microsoft.Build.Execution.BuildManager.BeginBuild.__InitializeLoggingService|64_0() Line 443 C#
Microsoft.Build.dll!Microsoft.Build.Execution.BuildManager.BeginBuild(Microsoft.Build.Execution.BuildParameters parameters) Line 360 C#
Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll!Microsoft.CodeAnalysis.MSBuild.ProjectBuildManager.StartBatchBuild(System.Collections.Generic.IDictionary globalProperties) Line 243 C#
Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll!Microsoft.CodeAnalysis.MSBuild.BuildHost.CreateBuildManager() Line 122 C#
Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll!Microsoft.CodeAnalysis.MSBuild.BuildHost.LoadProjectCore(string projectFilePath, string projectContent, string languageName) Line 205 C#
Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll!Microsoft.CodeAnalysis.MSBuild.BuildHost.LoadProject(string projectFilePath, string projectContent, string languageName) Line 176 C#
```

From discussion with @dibarbet we believe this is a regression. In the past, the usage pattern shown in the linked code did not result in multiple initialization of the BinaryLogger. We were thus able to log both the evaluation and build of a project to the same binlog file at design time.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.