-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Fix TerminalLogger IndexOutOfRangeException when replaying binlog with fewer nodes #12809
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Hello @@copilot, I noticed that you’re changing an .swr file or any file under src/Package/MSBuild.VSSetup.. Please make sure to validate this change by an experimental VS insertion. This is accomplished by pushing to an exp/* branch, which requires write permissions to this repo. |
…with fewer nodes Co-authored-by: YuliiaKovalova <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes an IndexOutOfRangeException that occurs when replaying a binary log with the TerminalLogger using fewer nodes than the original build. The issue arose because the logger initializes its _nodes array based on the replay's node count, but events in the binlog reference NodeIds from the original build with potentially higher values.
Key changes:
- Added dynamic array resizing via
EnsureNodeCapacity()method - Protected all
_nodesarray accesses in event handlers to ensure capacity before indexing - Added test case for binlog replay with mismatched node counts
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Build/Logging/TerminalLogger/TerminalLogger.cs | Added EnsureNodeCapacity() method with exponential growth strategy and updated all three array access points (ProjectStarted, UpdateNodeStatus, MessageRaised) to call it before indexing |
| src/Build.UnitTests/TerminalLogger_Tests.cs | Added regression test that builds with /m:4 and replays with nodeCount: 1 to verify the fix works |
| await Verify(_outputWriter.ToString(), _settings).UniqueForOSPlatform().UseParameters(runOnCentralNode); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
syntax errors
| } | ||
|
|
||
| [Fact] | ||
| public void ReplayBinaryLogWithFewerNodesThanOriginalBuild() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the test does not make sense, the build of this project will run on one node even though /m:4 is specified so no error will be produced when replayed with lower /m
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the test does not make sense, the build of this project will run on one node even though /m:4 is specified so no error will be produced when replayed with lower /m
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in e73419f. The test now creates three separate projects and builds them in parallel using MSBuild task with BuildInParallel='true', which ensures multiple NodeIds are present in the binlog.
| { | ||
| _restoreContext = c; | ||
| int nodeIndex = NodeIndexForContext(e.BuildEventContext); | ||
| EnsureNodeCapacity(nodeIndex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems strange to ensure node capacity in the common path and it not being something specific for replay mode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot limit to replay mode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in e73419f. Added _isReplayMode flag that is set when IEventSource is IBinaryLogReplaySource. EnsureNodeCapacity now only resizes the array when in replay mode, so normal builds are not affected.
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
…lel builds Co-authored-by: YuliiaKovalova <[email protected]>
Replaying a binary log with terminal logger fails when the replay uses fewer nodes (
/m:1) than the original build. The logger initializes its_nodesarray based on the replay's node count, but events in the binlog reference NodeIds from the original build, causing anIndexOutOfRangeException.Context
During binary log replay, the TerminalLogger is initialized with the node count from the replay command (e.g.,
/m:1), but the binary log contains events with NodeIds from the original build which may have used more nodes (e.g.,/m:4or/m:8). This mismatch causes an IndexOutOfRangeException when the logger tries to access array indices that don't exist.Changes Made
_isReplayModeflag to detect when running in binary log replay mode by checking ifIEventSourceisIBinaryLogReplaySourceEnsureNodeCapacity()method to dynamically resize_nodesarray only during replay mode when encountering NodeIds beyond current capacitylock (_lock)) to prevent race conditions with the refresher thread_nodesarray accesses (inUpdateNodeStatus,ProjectStarted,MessageRaised) to callEnsureNodeCapacitybefore indexingMSBuildtask withBuildInParallel='true'to ensure NodeIds > 1 are actually present in the binlogTesting
/m:8→ replay with/m:1using terminal logger: SUCCESSNotes
The fix is scoped specifically to replay scenarios - normal builds are completely unaffected by the dynamic resizing logic, ensuring zero performance impact on regular build operations. The replay mode detection (
_isReplayModeflag) ensures the array resizing only occurs when actually needed, and the double-checked locking pattern ensures thread safety without impacting performance during normal array accesses.Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.