Skip to content

Preserve virtual task environments in TaskHosts - #15032

Draft
rainersigwald wants to merge 8 commits into
mainfrom
rainersigwald-coordinator-restore-deadlock
Draft

rainersigwald wants to merge 8 commits into
mainfrom
rainersigwald-coordinator-restore-deadlock

Conversation

@rainersigwald

@rainersigwald rainersigwald commented Sep 14, 2026

Copy link
Copy Markdown
Member

Related issue(s):

Fixes: #14986

copilot writes:

Context

Under -mt, a task can add an environment variable before any TaskHost launches without changing the parent's process-global environment. The variable reaches the first task configuration, but TaskHost reconciliation compares that configuration with its inherited startup environment and treats every difference as a bitness adjustment. It consequently replaces the supplied value with the startup value, including deleting a newly added variable. The first task's environment was incorrectly serving as a proxy for the launcher's environment at process creation.

For static-graph restore, this strips MSBUILDCOORDINATORGRANTID from the RestoreTaskEx TaskHost. The nested NuGet process then requests capacity held by its waiting parent, causing a deadlock.

Changes Made

Make the supplied task environment authoritative for ordinary variables. Restrict startup reconciliation to the six documented Windows WOW64 architecture/Program Files variables, retaining their existing forward and reverse mappings. Unix hosts apply none of these Windows-specific adjustments. This corrects the reconciliation policy rather than special-casing the coordinator token or adding a launch-time environment exchange.

Add regression coverage for environment additions/replacements/removals, task mutations, host reuse, concurrent build managers, cross-bitness execution, nested coordinator grants, and static-graph restore. Update the related documentation.

Compatibility

The correction uses existing Change Wave 18.12. MSBUILDDISABLEFEATURESFROMVERSION=18.12 restores legacy reconciliation and can reintroduce the deadlock. No public APIs, diagnostics, or packet formats change. The modern .NET and .NET Framework hosts receive the fix; the separate legacy CLR2 host is unchanged.

Testing

Validation of the original fix, before subsequent merges from main:

  • Before the fix, three MT regression cases failed as expected: addition lost, replacement reverted, and removal resurrected.
  • build.cmd -v quiet succeeded with no warnings or errors. Bootstrap help and the repository sample build also succeeded.
  • 91 focused cases passed across net472 and net11.0. Coordinator cases require both parent and child to receive grants under a one-node budget; static-graph restore uses cleared package sources.
  • Two existing apphost checks passed with SourceLink disabled to bypass an SDK task-construction failure also reproduced under legacy reconciliation.

Not rerun after the latest merges from main. Actual Unix execution remains for CI; the policy tests cover the Unix branch.

Dependencies and Follow-up

None. This does not depend on enlightening NuGet's static-graph restore task.

rainersigwald and others added 8 commits September 8, 2026 18:25
Restrict startup reconciliation to documented Windows architecture variables so virtualized task environments, including coordinator grant IDs, survive task-host execution. Preserve legacy reconciliation behind the Wave 18.12 opt-out.

Cover snapshot changes, host reuse, concurrent builds, cross-bitness execution, nested grants, and static-graph restore; document the corrected behavior.

Fixes #14986

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deadlock when coordinator, static-graph restore, and MT are all used

1 participant