BinaryLogger crashes child node with ObjectDisposedException in EnumerateMetadata
- Dominant language
- C#
- Stars
- 5.5k
- Forks
- 1.5k
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 141
Description
## Summary
MSBuild intermittently crashes with `MSB4166` (child node exited prematurely) due to a race condition in the BinaryLogger. The root cause is a `System.ObjectDisposedException` thrown when `BinaryLogger.Write` attempts to enumerate `ImmutableDictionary` metadata that has been concurrently disposed.
Tracked as a Known Build Error in dotnet/sdk: https://github.com/dotnet/sdk/issues/55076
## Stack trace
```
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'SortedInt32KeyNode1+Enumerator[ImmutableDictionary2+HashBucket[...]]'
at System.Collections.Immutable.SortedInt32KeyNode1.Enumerator.MoveNext()
at System.Collections.Immutable.ImmutableDictionary2.Enumerator.MoveNext()
at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.EnumerateMetadata(...)
at Microsoft.Build.Logging.BuildEventArgsWriter.Write(ITaskItem item, ...)
at Microsoft.Build.Logging.BinaryLogger.Write(BuildEventArgs e)
```
## Reproduction
- Non-deterministic; occurs intermittently in CI builds that use `/bl` (binary logging).
- Observed in dotnet/sdk CI on various test legs. Retry always succeeds.
- Example failing build: https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1486641
## Root Cause
The lazy `EnumerateMetadata` enumeration over `ImmutableDictionary` in `ProjectItemInstance.TaskItem` races with disposal on another thread during binary log writing.
## Related
- Draft PR believed to fix this: https://github.com/dotnet/msbuild/pull/14115
- SDK known issue tracking: https://github.com/dotnet/sdk/issues/55076
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reading ProjectItemInstance.TaskItem.EnumerateMetadata and the BinaryLogger.Write/BuildEventArgsWriter.Write path shown in the stack trace, then reproduce with /bl in the referenced CI scenario if possible. Done means binary logging no longer crashes a child node with ObjectDisposedException during metadata enumeration; compare the behavior with draft PR #14115.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100