[Xamarin.Android.Build.Tasks] Fix _CreateAar race under parallel build#11527
Draft
jonathanpeppers wants to merge 4 commits into
Draft
[Xamarin.Android.Build.Tasks] Fix _CreateAar race under parallel build#11527jonathanpeppers wants to merge 4 commits into
jonathanpeppers wants to merge 4 commits into
Conversation
Fixes: #11514 Under parallel build (`-m`), library projects with `<GeneratePackageOnBuild>true</GeneratePackageOnBuild>` could fail with: error XARLP7024: System.IO.IOException: The process cannot access the file '.../<assembly>.aar' because it is being used by another process. at Microsoft.Android.Build.Tasks.Files.HashFile(...) at Xamarin.Android.Tasks.ResolveLibraryProjectImports.Extract(...) `_CreateAar` was being scheduled up to *three* times for a single library build, on two distinct MSBuild project instances: * Once from `BuildDependsOn`. * Once from `_UpdateAndroidResourcesDependsOn` on the regular `Build` chain. * Once more from `_UpdateAndroidResourcesDependsOn` on a Pack-dispatched project instance entered via `_GetFrameworkAssemblyReferences`. Because that instance has different global properties (NuGet pack's per-TFM inner-target dispatch), MSBuild does not dedupe it and may run it on a fresh worker node, opening a write/write or write/read race against consumers that read the `.aar` via `Files.HashFile`. `_UpdateAndroidResources` is the aapt2/resource-designer step; producing the publish artifact (`.aar`) is unrelated. The AAR is still produced because `_CreateAar` remains in `BuildDependsOn` for non-application projects, and Pack depends on `Build`, so a normal build and `dotnet pack` both still create it. Removing `_CreateAar` from `_UpdateAndroidResourcesDependsOn` collapses the count to a single invocation per build, eliminating the race window and the redundant AAR rewrites. Added a regression test in `IncrementalBuildTest` that builds a library with `GeneratePackageOnBuild=true` at `LoggerVerbosity.Detailed` and asserts that `Target "_CreateAar" in file ...` appears exactly once in the build log. Verified against the repro project on the issue: the count drops from 3 to 1 with the fix applied. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Removes _CreateAar from _UpdateAndroidResourcesDependsOn to prevent it from being invoked multiple times during a single build (notably via NuGet pack's per-TFM inner-target dispatch), which was causing a write/read race on the .aar file under parallel builds (XARLP7024). _CreateAar is still wired through BuildDependsOn for non-application projects, so dotnet build and dotnet pack continue to produce the AAR.
Changes:
- Remove
_CreateAarfrom_UpdateAndroidResourcesDependsOninMicrosoft.Android.Sdk.BuildOrder.targets. - Add
IncrementalBuildTest.CreateAarRunsOnceWithGeneratePackageOnBuildasserting_CreateAarruns exactly once whenGeneratePackageOnBuild=true.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets | Drops _CreateAar from the resource-update dependency chain to eliminate redundant invocations and the race window. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs | New regression test verifying _CreateAar executes exactly once for a library with GeneratePackageOnBuild=true. |
The `CreateAar` task writes each item in `@(JarFiles)` into the output `.aar` archive at `libs/<hash>.jar`. Today nothing protects against the same archive path being written twice: e.g. `_CompileBindingJava` adds the binding classes zip to both `@(EmbeddedJar)` and `@(AndroidJavaLibrary)`, and the input groups can otherwise accumulate duplicates across target invocations. Calling `aar.AddStream` repeatedly with the same path produces multiple zip entries with identical names, which the `DotNetPack` test now catches as `found 3` jars where only 2 unique paths exist. Track archive paths in a `HashSet<string>` and skip duplicates. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This reverts commit 3c9b3fb.
…n _CreateAar After removing _CreateAar from _UpdateAndroidResourcesDependsOn (to fix the parallel-build race in #11514), the DotNetPack test started failing because the .aar inside the .nupkg contained an extra .jar. Previously, dotnet pack''s inner _GetFrameworkAssemblyReferences evaluation implicitly re-ran _CreateAar through the resource chain (see #10270). In that inner evaluation _CompileBindingJava had not run, so the binding classes zip was not in @(EmbeddedJar)/@(AndroidJavaLibrary), and the resulting .aar (which overwrote the outer Build evaluation''s .aar) did not contain it. The .nupkg picked up that smaller .aar. Removing _CreateAar from the resource chain eliminated that overwrite, so the outer Build evaluation''s .aar (with the binding zip included in both EmbeddedJar and AndroidJavaLibrary) ended up in the .nupkg. Make _IncludeAarInNuGetPackage explicitly depend on _CreateAar so the inner per-TFM Pack evaluation still produces the .aar layout intended for the .nupkg, without relying on the resource-chain side effect that caused the original race. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Member
Author
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
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.
Fixes: #11514
Why
Under parallel build (
-m), library projects with<GeneratePackageOnBuild>true</GeneratePackageOnBuild>can intermittently fail with:The reporter's
mini.binlogshows_CreateAarrunning in two distinct project instances of the same library csproj, and a local repro shows it running three times for a singledotnet build:BuildDependsOn._UpdateAndroidResourcesDependsOnon the regularBuildchain._UpdateAndroidResourcesDependsOnon a Pack-dispatched project instance entered via_GetFrameworkAssemblyReferences(NuGet pack's per-TFM inner-target dispatch). That instance has different global properties, so MSBuild does not dedupe it and may run it on a fresh worker node, opening a write/write or write/read race against consumers that read the.aarviaFiles.HashFile.Approach
_UpdateAndroidResourcesis the aapt2/resource-designer step; producing the publish artifact (.aar) is unrelated. Remove_CreateAarfrom_UpdateAndroidResourcesDependsOn. The AAR is still produced because_CreateAarremains inBuildDependsOnfor non-application projects, and Pack depends onBuild, sodotnet buildanddotnet packboth still create it.This collapses the count to a single invocation per build, eliminating the race window and the redundant AAR rewrites at the root rather than papering over them with reader retries or atomic writes.
Test
Added
IncrementalBuildTest.CreateAarRunsOnceWithGeneratePackageOnBuild: builds a library withGeneratePackageOnBuild=trueatLoggerVerbosity.Detailedand assertsTarget "_CreateAar" in file ...appears exactly once in the build log.Verified against the issue's repro project: count drops from 3 to 1 with the fix.