Make Runtime=NET task host handshake architecture-agnostic#13890
Make Runtime=NET task host handshake architecture-agnostic#13890ViktorHofer wants to merge 4 commits into
Conversation
IsAllowedBitnessMismatch is the .NET task host child-side relaxation that lets a parent without an architecture bit on the wire (typically a .NET Framework MSBuild) connect to an SDK child that runs on x64. On Windows-ARM the SDK child runs as arm64 instead, but the function only considered expectedIsX64, so any arm64 child rejected the connection -> the launch times out and Runtime="NET" tasks fail with MSB4216. Also tolerate expectedIsArm64. True cross-arch mismatches (parent X64 vs child Arm64, or vice versa) remain rejected. Make the method internal static so the test project can exercise the tolerance matrix directly. The previous instance method did not touch any instance state. Partial fix for dotnet#13879 (Bug A). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes a child-side handshake check that prevented .NET Framework MSBuild parents from launching a Runtime="NET" task host on Windows-ARM. IsAllowedBitnessMismatch previously only tolerated an x64-expecting child when the parent sent no architecture bit; it now tolerates arm64-expecting children as well, while still rejecting true cross-arch mismatches (X64↔Arm64). The method is also promoted to internal static to make it directly unit-testable.
Changes:
- Extend
IsAllowedBitnessMismatchto acceptexpectedIsArm64in addition toexpectedIsX64. - Convert the method to
internal staticand refresh its doc comment. - Add unit tests covering the no-arch-bit-parent tolerance matrix (x64/arm64 child) and rejection of true cross-arch mismatches.
Show a summary per file
| File | Description |
|---|---|
| src/Shared/NodeEndpointOutOfProcBase.cs | Tolerate arm64-expecting child in bitness mismatch check; expose as internal static; update XML doc. |
| src/Build.UnitTests/BackEnd/NodeEndpointOutOfProcBase_Tests.cs | New #if NET tests for the tolerance matrix and cross-arch rejection. |
Copilot's findings
- Files reviewed: 2/2 changed files
- Comments generated: 0
There was a problem hiding this comment.
Review Summary — PR #13890
Well-scoped bug fix extending the .NET task host handshake tolerance to arm64 children. The logic change is correct and the approach is sound.
Findings
| # | Dimension | Severity | Summary |
|---|---|---|---|
| 1 | Test Coverage & Completeness | MODERATE | Missing test for "no-arch parent → no-arch child" (the path where receivedIsX86==true but method returns false) |
| 2 | Documentation Accuracy | NIT | Inherited mask comment has version/flags description inverted |
Clean Dimensions (22/24)
Backwards Compatibility ✓ · ChangeWave ✓ · Performance ✓ · Error Messages ✓ · Logging ✓ · String Comparison ✓ · API Surface ✓ · Target Authoring ✓ · Design ✓ · Cross-Platform ✓ · Code Simplification ✓ · Concurrency ✓ · Naming ✓ · SDK Integration ✓ · Idiomatic C# ✓ · File I/O ✓ · Build Infrastructure ✓ · Scope & PR Discipline ✓ · Evaluation Model ✓ · Correctness ✓ · Dependency Mgmt ✓ · Security ✓
Notes
- The
private → internal staticvisibility change is appropriate for testability; the class is alreadyinternaland the method is a pure stateless predicate. - The behavioral change is strictly a relaxation (accepts arm64 where previously only x64 was accepted), so no ChangeWave is needed.
- The fix correctly rejects true cross-arch mismatches (e.g., parent declares X64 but child expects Arm64).
Note
🔒 Integrity filter blocked 2 items
The following items were blocked because they don't meet the GitHub integrity level.
- #13890
pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved". - #13890
pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
To allow these resources, lower min-integrity in your GitHub frontmatter:
tools:
github:
min-integrity: approved # merged | approved | unapproved | noneGenerated by Expert Code Review (on open) for issue #13890 · ● 5.5M
For NET task host launches the child process's architecture is determined by what the .NET SDK shipped (x64 today, arm64 in the future), not by the parent's process architecture. Emitting the parent's arch bit creates a wire-level mismatch with already-shipped SDK children whose arch differs (e.g. arm64 VS launching an x64 SDK MSBuild.dll, or amd64 VS launching an arm64 SDK MSBuild.dll). The existing child-side IsAllowedBitnessMismatch tolerance only accepts "parent sent no arch bit", so this currently fails with MSB4216. In CommunicationsUtilities.GetHandshakeOptions, suppress the X64/Arm64 bit when invoked by the parent for a NET task host (detected by Runtime="net" in the explicit TaskHostParameters). The child path (TaskHostParameters .Empty) is unaffected so already-deployed parents that still emit an arch bit continue to match. Combined with the child-side Arm64 tolerance in this PR, every parent/ child architecture combination now connects against every already-shipped SDK that has the original (x64-only) tolerance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add NoArchBitParent_NoArchBitChild_NotTolerated test (catches a regression that would simplify the return to just receivedIsX86). - Fix inverted comment on the 0x00FFFFFF mask (lower 24 bits are flags, upper byte is version). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@rainersigwald it would be great if you could also take a look :) Just want to be careful. |
…handshake comments - Remove the speculative 'arm64 in the future' note and condense the verbose NET task host arch-bit suppression comment to the underlying rule. - Rename parent/child to worker node/TaskHost node in comments, the isNetTaskHostWorkerNode variable, and the handshake unit tests. - Fix the stale inverted handshake mask comment at the IsAllowedBitnessMismatch call site. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@rainersigwald please approve if the changes look good to you |
| /// True cross-arch mismatches (e.g. worker node sent X64 but TaskHost node expects | ||
| /// Arm64, or vice versa) remain rejected. |
There was a problem hiding this comment.
But we're missing "worker node wanted x86" right, because it's indistinguishable from "didn't care"?
|
@ViktorHofer mergeable? or do you plan to take action on last rainer's comment? |
Summary
Runtime="NET"task host launches fail withMSB4216whenever the worker node and TaskHost node architectures don't line up the way the original implementation expected. Tracked as #13879 (Bug A).Two coordinated handshake changes — one on each side — close every reasonable worker/TaskHost arch combination:
1. Worker node side —
CommunicationsUtilities.GetHandshakeOptionsFor a NET task host the launched TaskHost node's architecture is whatever the .NET SDK shipped, not the worker node's. Emitting the worker node's arch bit produces a wire-level mismatch with already-shipped SDK TaskHost nodes whose arch differs.
Suppress the
X64/Arm64bit when invoked by the worker node for a NET task host (detected byRuntime="net"in the explicitTaskHostParameters). The TaskHost-node path (TaskHostParameters.Empty) is unaffected, so already-deployed worker nodes that still emit an arch bit continue to match.2. TaskHost node side —
NodeEndpointOutOfProcBase.IsAllowedBitnessMismatchThe .NET task host side relaxation that lets a worker node without an arch bit on the wire connect to an SDK TaskHost node. Previously only tolerated
expected = X64, so any arm64 SDK TaskHost node rejected the connection. Now also toleratesexpected = Arm64. True cross-arch mismatches (workerX64↔ TaskHostArm64) remain rejected.Method is promoted to
internal staticso the test project can exercise the tolerance matrix directly. It was a stateless pure predicate already.Effect across worker node / SDK combinations
current= behavior with this PR applied (worker-node change in VS MSBuild, TaskHost-node change in a future SDK). For each combo, "current behavior" notes whether the SDK side needs to update.expectedIsX64tolerance)expectedIsArm64toleranceWhere each fix takes effect
expectedIsX64tolerance already covers the TaskHost node)The reported binlog (Roslyn build on Windows-ARM, SDK 10.0.108, x86 VS 18 MSBuild worker node) is the first row — needs the SDK side to pick this up.
Tests
src/Build.UnitTests/BackEnd/NodeEndpointOutOfProcBase_Tests.cs(6 cases):NoArchBitWorkerNode_X64TaskHost_IsToleratedNoArchBitWorkerNode_Arm64TaskHost_IsToleratedX64WorkerNode_X64TaskHost_NotConsideredMismatchX64WorkerNode_Arm64TaskHost_NotToleratedArm64WorkerNode_X64TaskHost_NotToleratedNoArchBitWorkerNode_NoArchBitTaskHost_NotTolerated(guards against a future simplification toreturn receivedIsX86;)src/Build.UnitTests/BackEnd/CommunicationsUtilities_Tests.cs(5 cases):GetHandshakeOptions_NetTaskHostWorkerNode_SuppressesArchBit× { x64, arm64, x86 }GetHandshakeOptions_NonNetTaskHostWorkerNode_KeepsX64ArchBitGetHandshakeOptions_NonNetTaskHostWorkerNode_KeepsArm64ArchBitGetHandshakeOptions_NetTaskHostNode_KeepsArchBitAll 11 pass on net10.0.
References