Skip to content

Guard ActivelyBuildingTargets removal against stale request cleanup after cancellation timeout - #14732

Draft
AR-May with Copilot wants to merge 3 commits into
mainfrom
copilot/resolve-caching-issue
Draft

Guard ActivelyBuildingTargets removal against stale request cleanup after cancellation timeout#14732
AR-May with Copilot wants to merge 3 commits into
mainfrom
copilot/resolve-caching-issue

Conversation

Copilot AI commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Context

BuildManager.Reset() clears BuildRequestConfiguration.ActivelyBuildingTargets at end-of-build, but TargetBuilder removed entries from that table by target name only, ignoring the owning request ID. If a request's cancellation times out while the task keeps running, it can resume later and remove an entry that a newer request (reusing the same retained configuration) has since recorded for the same target name — making the configuration falsely appear inactive. This can let another request build the same target concurrently, corrupt circular-dependency detection, or let CacheIfPossible() cache the ProjectInstance while it's still in use.

Changes Made

  • BuildRequestConfiguration: added RemoveActivelyBuildingTargetIfOwnedBy(targetName, globalRequestId), which only removes the entry if it is still recorded as owned by the given request ID.
  • TargetBuilder: replaced all 4 unconditional ActivelyBuildingTargets.Remove(name) call sites (end-of-build stack cleanup, error-execution catch, target-completed cleanup, dependency-pop-on-failure) with the new guarded removal.
// Before: any request could clear a target owned by someone else
_requestEntry.RequestConfiguration.ActivelyBuildingTargets.Remove(currentTargetEntry.Name);

// After: only removes if still owned by the calling request
_requestEntry.RequestConfiguration.RemoveActivelyBuildingTargetIfOwnedBy(
    currentTargetEntry.Name, _requestEntry.Request.GlobalRequestId);

Testing

Added a unit test in BuildRequestConfiguration_Tests verifying a stale owner's removal is a no-op while the current owner's removal succeeds. Existing TargetBuilder_Tests and RequestBuilder_Tests continue to pass.

Notes

No behavioral change for the common case where the current request still owns the entry; this only prevents cross-request interference during the stale-cleanup race described in the issue.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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.

Copilot AI and others added 2 commits August 18, 2026 11:30
Co-authored-by: AR-May <67507805+AR-May@users.noreply.github.com>
Co-authored-by: AR-May <67507805+AR-May@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix caching issue after stale /mt request cleanup Guard ActivelyBuildingTargets removal against stale request cleanup after cancellation timeout Aug 18, 2026
Copilot AI requested a review from AR-May August 18, 2026 11:35
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.

An active ProjectInstance can be cached after stale  /mt  request cleanup

2 participants