migrate PickBestRid#54489
Conversation
There was a problem hiding this comment.
Pull request overview
This PR migrates the PickBestRid MSBuild task to MSBuild’s multi-threaded task execution model by implementing IMultiThreadableTask and routing file path resolution through TaskEnvironment, with tests intended to validate behavior in isolated vs fallback execution modes.
Changes:
- Updated
PickBestRidto opt into multi-threaded execution and resolveRuntimeGraphPathviaTaskEnvironment.GetAbsolutePath(...)before file access and runtime graph loading. - Added a new unit test file to validate relative-path resolution and error-message behavior (including avoiding absolutized path leaks).
- Added a coarse-grained lock in
RuntimeGraphCachearound task-object caching of runtime graphs.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| test/Microsoft.NET.Build.Tasks.Tests/GivenAPickBestRidMultiThreading.cs | Adds tests around TaskEnvironment-based path resolution and error messaging for PickBestRid. |
| src/Tasks/Microsoft.NET.Build.Tasks/RuntimeGraphCache.cs | Adds locking around runtime graph caching via BuildEngine registered task objects. |
| src/Tasks/Microsoft.NET.Build.Tasks/PickBestRid.cs | Implements IMultiThreadableTask, uses TaskEnvironment to resolve runtime graph path prior to file operations and caching. |
| public class GivenAPickBestRidMultiThreading | ||
| { | ||
| private const string RuntimeGraphContent = @"{ | ||
| ""runtimes"": { | ||
| ""any"": { ""#import"": [""base""] }, |
| string key = GetTaskObjectKey(runtimeJsonPath); | ||
|
|
||
| RuntimeGraph result; | ||
| object existingRuntimeGraphTaskObject = _buildEngine.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.AppDomain); | ||
| if (existingRuntimeGraphTaskObject == null) | ||
| lock (s_cacheLock) | ||
| { | ||
| result = JsonRuntimeFormat.ReadRuntimeGraph(runtimeJsonPath); | ||
|
|
||
| _buildEngine.RegisterTaskObject(key, result, RegisteredTaskObjectLifetime.AppDomain, true); | ||
| RuntimeGraph result; | ||
| object existingRuntimeGraphTaskObject = _buildEngine.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.AppDomain); | ||
| if (existingRuntimeGraphTaskObject == null) | ||
| { | ||
| result = JsonRuntimeFormat.ReadRuntimeGraph(runtimeJsonPath); | ||
|
|
||
| _buildEngine.RegisterTaskObject(key, result, RegisteredTaskObjectLifetime.AppDomain, true); | ||
| } | ||
| else | ||
| { | ||
| result = (RuntimeGraph)existingRuntimeGraphTaskObject; | ||
| } | ||
|
|
||
| return result; | ||
| } |
OvesN
left a comment
There was a problem hiding this comment.
LGTM, but I would try different solution with the lock. Otherwise this migration seems fine
| RuntimeGraph result; | ||
| object existingRuntimeGraphTaskObject = _buildEngine.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.AppDomain); | ||
| if (existingRuntimeGraphTaskObject == null) | ||
| lock (s_cacheLock) |
There was a problem hiding this comment.
Locking here is the right think to do I think, but I think we can do something more granular than one global lock. We only really care about two threads colliding on the same taskObjectKey - so per-key locks would probably be better.
Summary
Migrates
PickBestRidto MSBuild's multithreaded task execution model by opting intoIMultiThreadableTaskand routing path resolution throughTaskEnvironment.Changes
PickBestRid.cs[MSBuildMultiThreadableTask]and implementedIMultiThreadableTaskwithTaskEnvironment = TaskEnvironment.Fallback.RuntimeGraphPathviaTaskEnvironment.GetAbsolutePath(...)beforeFile.ExistsandRuntimeGraphCache.GetRuntimeGraph.RuntimeGraphPathin error messages (no absolutized leak).GivenAPickBestRidMultiThreading.cs(new) — 4 correctness tests:ItResolvesRelativeRuntimeGraphPathAgainstProjectDirectoryMatchingRidOutputContainsOnlyRidNoPathPrefixMatchingRidoutput.MissingFileErrorContainsOriginalRelativePathNotAbsolutizedItProducesIdenticalOutcomeInFallbackAndIsolatedModes_SuccessFallbackand isolatedTaskEnvironment.Validation
PickBestRid.cs.GivenAPickBestRidtests: 6/6 still pass.