Commit a309493
authored
fix: resolve MSB3491 race condition in WriteLaunchers parallel builds (#199)
## Problem
`WriteLaunchers` wrote build variables to a hardcoded global temp path:
```
%TEMP%\IntelliTect.MultiTool.BuildVariables.tmp
```
When a solution has multiple projects referencing this package, `dotnet
build` builds them in parallel. All projects resolved to the **same
absolute file path**, and `WriteLinesToFile` with `Overwrite="true"` is
not atomic (delete-then-create). Two parallel project builds racing on
that path caused:
```
error MSB3491: Could not write lines to file "...\IntelliTect.MultiTool.BuildVariables.tmp".
Cannot create a file when that file already exists.
```
There was also a **correctness bug**: even when writes didn't collide,
the winning writer was non-deterministic — the file could end up
containing variables from any project in the solution, not the one that
would consume it at runtime.
## Fix
Write the build variables file to `$(OutDir)` — each project's output
directory — which is already unique per project and per TFM. Update the
C# reader to look in `AppContext.BaseDirectory` instead of
`Path.GetTempPath()`, since `AppContext.BaseDirectory` resolves to the
same output directory at runtime.
### Changes
**`IntelliTect.Multitool/Build/IntelliTect.Multitool.targets`**
- Remove the `TempStagingPath` property (was the source of the shared
path)
- Collapse two conditional `WriteLinesToFile` calls into one
unconditional write to
`$(OutDir)IntelliTect.MultiTool.BuildVariables.tmp`
**`IntelliTect.Multitool/RepositoryPaths.cs`**
- `Path.GetTempPath()` → `AppContext.BaseDirectory` in `BuildVariables`
initializer
**`IntelliTect.Multitool.AotTest/Program.cs`**
- Update stale comment to reflect the new file location
## Why `$(OutDir)` + `AppContext.BaseDirectory`
| Property | Value |
|---|---|
| Parallel-safe | ✅ Each project has a unique output dir |
| LUT-compatible | ✅ VS LUT shadow-copies the entire output dir;
`AppContext.BaseDirectory` follows |
| AOT-safe | ✅ `AppContext.BaseDirectory` works in single-file/AOT
(unlike `Assembly.Location`) |
| Cross-platform | ✅ `$(OutDir)` always ends with a path separator;
valid on Windows and Linux |1 parent 6659c99 commit a309493
3 files changed
Lines changed: 3 additions & 5 deletions
File tree
- IntelliTect.Multitool.AotTest
- IntelliTect.Multitool
- Build
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
23 | | - | |
| 23 | + | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
28 | 27 | | |
29 | 28 | | |
30 | 29 | | |
31 | 30 | | |
32 | 31 | | |
33 | 32 | | |
34 | 33 | | |
35 | | - | |
36 | | - | |
| 34 | + | |
37 | 35 | | |
38 | 36 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| |||
0 commit comments