[IBuildEngine callbacks] Stage 2: RequestCores/ReleaseCores#13306
Merged
JanProvaznik merged 7 commits intodotnet:mainfrom Mar 2, 2026
Merged
[IBuildEngine callbacks] Stage 2: RequestCores/ReleaseCores#13306JanProvaznik merged 7 commits intodotnet:mainfrom
JanProvaznik merged 7 commits intodotnet:mainfrom
Conversation
New IPC packet pair for forwarding IBuildEngine9.RequestCores() and ReleaseCores() from TaskHost to the owning worker node. TaskHostCoresRequest (0x22) uses a single packet type with an IsRelease bool to distinguish RequestCores from ReleaseCores — both operations share the same int parameter semantics (core count) and response shape (granted cores or acknowledgment). TaskHostCoresResponse (0x23) returns GrantedCores for RequestCores calls and 0 as acknowledgment for ReleaseCores calls. Both implement ITaskHostCallbackPacket for request/response correlation via RequestId, following the Stage 1 pattern (TaskHostIsRunningMultipleNodes*). The NodePacketType enum values 0x22/0x23 were already reserved; this commit updates their doc comments to use 'owning worker node' terminology. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace 'throw NotImplementedException()' stubs with callback-based forwarding using the Stage 1 SendCallbackRequestAndWaitForResponse<T> infrastructure. Both methods: - Validate input (requestedCores/coresToRelease > 0) before IPC roundtrip, matching the in-process TaskHost's fail-fast behavior - Check CallbacksSupported gate — when disabled, RequestCores returns 0 and ReleaseCores is no-op, both logging MSB5022 - Send TaskHostCoresRequest and block on TaskHostCoresResponse via TCS Register TaskHostCoresResponse handler in the constructor and add the response routing case to HandlePacket's switch statement. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Register TaskHostCoresRequest handler and add HandleCoresRequest() which forwards calls to the in-process TaskHost's IBuildEngine9 implementation. The OOP TaskHostNode is a thin proxy — the real implicit-core accounting and scheduler communication happens in the in-process TaskHost class on the worker node side. HandleCoresRequest dispatches based on IsRelease: - RequestCores: forwards to engine9.RequestCores(), returns GrantedCores - ReleaseCores: forwards to engine9.ReleaseCores(), returns 0 (ack) When _buildEngine doesn't implement IBuildEngine9 (shouldn't happen in practice), RequestCores returns 0 and ReleaseCores is no-op — matching the HandleIsRunningMultipleNodesRequest pattern for IBuildEngine2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
RequestCoresTask is a test task that calls IBuildEngine9.RequestCores(N) and optionally ReleaseCores. It exposes GrantedCores as an output property for assertion. Linked into ExampleTask.csproj for E2E cross-runtime use. TestNetTaskResourceCallback/ is the E2E test project that runs RequestCoresTask via TaskHostFactory with Runtime='NET', mirroring the TestNetTaskCallback/ project from Stage 1. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Packet serialization (4 tests): - TaskHostCoresRequest round-trip for RequestCores and ReleaseCores - TaskHostCoresResponse round-trip for granted cores and acknowledgment Integration (5 tests): - RequestCores via explicit TaskHostFactory — verifies granted >= 1 - RequestCores + ReleaseCores full cycle — verifies no errors - RequestCores auto-ejected in MT mode — verifies TaskHost forwarding - RequestCores fallback when callbacks disabled — verifies MSB5022 - IsRunningMultipleNodes fallback (Stage 1, unchanged) E2E cross-runtime (1 test): - NetTaskHost_CallbackRequestCoresTest via bootstrapped MSBuild Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
4601b9a to
086f16b
Compare
JanProvaznik
added a commit
to JanProvaznik/msbuild
that referenced
this pull request
Feb 27, 2026
- Mark RequestCores/ReleaseCores as implemented in status table - Rename TaskHostResourceRequest/Response to TaskHostCoresRequest/Response - Update phased rollout table with PR dotnet#13306 - Replace Stage 2 design considerations with implementation summary Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
086f16b to
89594d2
Compare
Member
Author
|
@AR-May @rainersigwald this one should be simple, it is conceptually the same as the previous PR, the juicy one will be the next one. |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds Stage 2 of TaskHost IBuildEngine callback forwarding by implementing IBuildEngine9.RequestCores / ReleaseCores over the existing callback packet infrastructure, enabling resource-aware tasks to run out-of-proc without NotImplementedException.
Changes:
- Introduces
TaskHostCoresRequest/TaskHostCoresResponsepackets and newNodePacketTypeentries. - Implements
RequestCores/ReleaseCoresforwarding inOutOfProcTaskHostNode(TaskHost side) and handles requests inTaskHostTask(worker node side). - Adds/updates unit + integration + E2E tests and a new ExampleNetTask asset for the callback.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Shared/TaskHostCoresRequest.cs | New callback request packet for RequestCores/ReleaseCores. |
| src/Shared/TaskHostCoresResponse.cs | New callback response packet returning granted cores / ack. |
| src/Shared/INodePacket.cs | Renames/defines packet types for cores request/response (0x22/0x23). |
| src/MSBuild/OutOfProcTaskHostNode.cs | Implements RequestCores/ReleaseCores via callback request/response + handler registration. |
| src/MSBuild/MSBuild.csproj | Includes new shared packet source files. |
| src/Build/Microsoft.Build.csproj | Includes new shared packet source files. |
| src/Build/Instance/TaskFactories/TaskHostTask.cs | Registers/handles cores request packet and forwards to in-proc IBuildEngine9. |
| src/Build.UnitTests/BackEnd/TaskHostCallbackPacket_Tests.cs | Adds round-trip serialization tests for new packets. |
| src/Build.UnitTests/BackEnd/TaskHostCallback_Tests.cs | Adds integration tests for RequestCores/ReleaseCores through TaskHost. |
| src/Build.UnitTests/BackEnd/RequestCoresTask.cs | Adds a test task that exercises RequestCores/ReleaseCores. |
| src/Build.UnitTests/NetTaskHost_E2E_Tests.cs | Adds E2E test to validate RequestCores callback across runtimes. |
| src/Build.UnitTests/TestAssets/ExampleNetTask/ExampleTask/ExampleTask.csproj | Links the new RequestCores test task into ExampleTask. |
| src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTaskResourceCallback/TestNetTaskResourceCallback.csproj | New test asset project invoking the RequestCores task via TaskHostFactory. |
| src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTaskResourceCallback/global.json | New global.json for the new test asset. |
src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTaskResourceCallback/global.json
Show resolved
Hide resolved
rainersigwald
approved these changes
Feb 27, 2026
JanProvaznik
added a commit
to JanProvaznik/msbuild
that referenced
this pull request
Mar 2, 2026
- Mark RequestCores/ReleaseCores as implemented in status table - Rename TaskHostResourceRequest/Response to TaskHostCoresRequest/Response - Update phased rollout table with PR dotnet#13306 - Replace Stage 2 design considerations with implementation summary Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rceCallback/global.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
lewing
added a commit
to dotnet/runtime
that referenced
this pull request
Mar 6, 2026
MSBuild PR dotnet/msbuild#13306 changed OutOfProcTaskHostNode.RequestCores from throwing NotImplementedException to returning 0 (and logging MSB5022) when callbacks aren't supported. This broke four tasks that only caught NotImplementedException: - EmccCompile: caused blazorwasm publish failure (dotnet/sdk#53300) - MonoAOTCompiler, ILStrip, EmitBundleBase: same latent bug The failure chain was: 1. RequestCores returns 0 (no exception thrown) 2. allowedParallelism becomes 0 3. Parallel.ForEach with MaxDegreeOfParallelism=0 throws 4. ReleaseCores(0) in finally block throws ArgumentOutOfRangeException Fix: track cores actually acquired separately. If RequestCores returns 0 or throws any exception, fall back to the original parallelism and skip ReleaseCores. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lewing
added a commit
to dotnet/runtime
that referenced
this pull request
Mar 6, 2026
MSBuild PR dotnet/msbuild#13306 changed OutOfProcTaskHostNode.RequestCores from throwing NotImplementedException to returning 0 (and logging MSB5022) when callbacks aren't supported. This broke four tasks that only caught NotImplementedException: - EmccCompile: caused blazorwasm publish failure (dotnet/sdk#53300) - MonoAOTCompiler, ILStrip, EmitBundleBase: same latent bug The failure chain was: 1. RequestCores returns 0 (no exception thrown) 2. allowedParallelism becomes 0 3. Parallel.ForEach with MaxDegreeOfParallelism=0 throws 4. ReleaseCores(0) in finally block throws ArgumentOutOfRangeException Fix: track cores actually acquired separately. If RequestCores returns 0 or throws any exception, fall back to the original parallelism and skip ReleaseCores. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Stage 2 of implementing IBuildEngine callback support in TaskHost. Stage 1 (#13149) established the packet infrastructure and implemented
IsRunningMultipleNodes. This PR addsRequestCores/ReleaseCores(IBuildEngine9) using the same pattern.Previously, tasks running in TaskHost that called
RequestCoresorReleaseCoreswould get aNotImplementedException. This blocked resource-aware tasks from properly coordinating CPU usage when running out-of-process.Partial fix for #12863
Changes Made
New Packets:
TaskHostCoresRequest(0x22) — single packet type for both operations, withIsReleasebool to distinguishRequestCoresvsReleaseCoresTaskHostCoresResponse(0x23) — returnsGrantedCores(int) for RequestCores, 0 for ReleaseCores acknowledgmentOutOfProcTaskHostNode (TaskHost side):
throw NotImplementedException()withSendCallbackRequestAndWaitForResponse<TaskHostCoresResponse>()requestedCores > 0,coresToRelease > 0) matching in-process behaviorCallbacksSupported— when disabled,RequestCoresreturns 0,ReleaseCoresis no-op (both log MSB5022)TaskHostCoresResponsein packet handler and route inHandlePacketswitchTaskHostTask (Worker node side):
TaskHostCoresRequestpacket handlerHandleCoresRequest(): forwardsRequestCores/ReleaseCoresto the in-processIBuildEngine9TaskHostclass — the OOP node is a thin proxyCallback Flow
sequenceDiagram participant Task as Task Thread<br/>(TaskHost) participant Main as Main Thread<br/>(TaskHost) participant Worker as TaskHostTask<br/>(Worker Node) Task->>Task: BuildEngine.RequestCores(N) Task->>Task: Create TaskHostCoresRequest(N, isRelease=false) Task->>Task: Store TCS in _pendingCallbackRequests[requestId] Task->>Worker: SendData(request) Task-->>Task: Block on TCS.Task Worker->>Worker: HandleCoresRequest(request) Worker->>Worker: granted = _buildEngine.RequestCores(N) Worker->>Main: SendData(TaskHostCoresResponse(granted)) Main->>Main: HandleCallbackResponse(response) Main->>Main: _pendingCallbackRequests[requestId].SetResult(response) Task-->>Task: TCS unblocks Task->>Task: return response.GrantedCoresTesting
RequestCores_WorksWithExplicitTaskHostFactory— verifies cores granted >= 1RequestAndReleaseCores_WorksWithExplicitTaskHostFactory— full request+release cycleRequestCores_WorksWhenAutoEjectedInMultiThreadedMode— MT auto-ejection to TaskHostRequestCores_LogsErrorWhenCallbacksNotSupported— MSB5022 fallbackIsRunningMultipleNodes_LogsErrorWhenCallbacksNotSupported— Stage 1 fallback (unchanged)NetTaskHost_CallbackRequestCoresTestvia bootstrapped MSBuildDocumentation
Updated
taskhost-threading.mdwith:Next Stages