dotnet / dotnet/msbuild

Race condition when publishing multiple projects can cause missed references

Open
#8,030 1 comment 3 reactions 0 assignees View on GitHub
backlog bug triaged
Dominant language
C#
Stars
5.5k
Forks
1.5k
Avg merge
1d 8h
Merged PRs (30d)
141

Description

This was reported via a Microsoft discussion group; this is a simplified repro.

The solution in [publish_bad_ordering.zip](https://github.com/dotnet/msbuild/files/9728840/publish_bad_ordering.zip), when built and published with

```sh
dotnet build
dotnet publish --no-build -bl -flp:v=diag -m:1
```

(`7.0.100-rc.1.22431.12`), will produce an incorrect `App3.deps.json` compared to publishing only `App3.csproj`:

```diff
diff --git "a/.\\IndividualPublish-App3.deps.json" "b/.\\SolutionPublish-App3.deps.json"
index 4b28e94..7dd6f87 100644
--- "a/.\\IndividualPublish-App3.deps.json"
+++ "b/.\\SolutionPublish-App3.deps.json"
@@ -20,12 +20,7 @@
"StyleCop.Analyzers.Unstable": "1.2.0.435"
}
},
- "StyleCop.Analyzers.Unstable/1.2.0.435": {},
- "App1/1.0.0": {
- "runtime": {
- "App1.dll": {}
- }
- }
+ "StyleCop.Analyzers.Unstable/1.2.0.435": {}
}
},
"libraries": {
@@ -47,11 +42,6 @@
"sha512": "sha512-ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==",
"path": "stylecop.analyzers.unstable/1.2.0.435",
"hashPath": "stylecop.analyzers.unstable.1.2.0.435.nupkg.sha512"
- },
- "App1/1.0.0": {
- "type": "project",
- "serviceable": false,
- "sha512": ""
}
}
}
\ No newline at end of file
```

This happens because the reference from App2→App3 causes parts of `ProjectReference` resolution to execute in a bad order:

```sh-session
❯ rg 'Done building target .(_SplitProjectReferencesByFileExistence|BuildOnlySettings|AssignProjectConfiguration|ResolveProjectReferences). in project .App3\.csproj' .\msbuild.log
48393:Done building target "_SplitProjectReferencesByFileExistence" in project "App3.csproj".: (TargetId:147)
51394:Done building target "BuildOnlySettings" in project "App3.csproj".: (TargetId:168)
51501:Done building target "AssignProjectConfiguration" in project "App3.csproj".: (TargetId:176)
51519:Done building target "ResolveProjectReferences" in project "App3.csproj".: (TargetId:178)
```

`_SplitProjectReferencesByFileExistence` depends on `@(ProjectReferenceWithConfiguration)`

https://github.com/dotnet/msbuild/blob/20ce296d6b3f4e63a511321c7e1a2f69a4ee63ef/src/Tasks/Microsoft.Common.CurrentVersion.targets#L1606-L1612

which is populated in `AssignProjectConfiguration`

https://github.com/dotnet/msbuild/blob/20ce296d6b3f4e63a511321c7e1a2f69a4ee63ef/src/Tasks/Microsoft.Common.CurrentVersion.targets#L1564-L1567

So if `_SplitProjectReferencesByFileExistence` runs first, the later `ResolveProjectReferences` will do nothing.

Missing project references at `publish --no-build` time can be somewhat benign, but in this case the project falls into a `$(_UseBuildDependencyFile) != true` case, because `@(_ExcludeFromPublishPackageReference)` is nonempty, because of the `ExcludeAssets="all"` on a `PackageReference` to `StyleCop.Analyzers`. That causes `App3.deps.json` to be recomputed with bad project-reference information, causing the absence of `App1`.

In the build that initially caused this report, this happened intermittently due to sometimes scheduling App3's publish before App2's reference to it, but the repro described above is deterministic because of limiting to a single build node with `-m:1`.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.