Try to make Copy task overwrite atomic (temp + rename)
- Dominant language
- C#
- Stars
- 5.5k
- Forks
- 1.5k
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 141
Description
## Idea
│ Note: this is not intended to fix the underlying problem. A build where two project evaluations write the same output path is already flawed, and that should be addressed at the source (e.g. by giving each configuration its own output directory). Making the Copy task atomic doesn't make those builds correct — it only makes already-flawed builds fail less often by removing the missing-file window the race depends on.
Make the `Copy` task overwrite an existing destination **atomically** — copy to a temp file in the same directory, then atomically rename it over the destination — instead of the current **delete-then-recreate** sequence.
Today `Copy` does a non-atomic `unlink(dest)` then `File.Copy(src, dest)` (`src/Tasks/Copy.cs` ~L324-329 / L382). For a brief window the destination does not exist on disk. In highly parallel builds where one project overwrites a shared output while other projects read that same file as a CopyLocal source, a reader can hit that gap and fail with **MSB3030: Could not copy the file "..." because it was not found.**
A temp + atomic rename (`rename(2)` on Linux/macOS, `MoveFileEx(MOVEFILE_REPLACE_EXISTING)` on Windows) closes the window: a concurrent reader always sees either the old complete file or the new complete file, never a missing/partial one. It also preserves the original reason for the delete (avoid writing *through* a hardlink/symlink and corrupting the link target, e.g. the NuGet cache — see #9250).
**Make sure the change does not introduce any performance degradation** vs. the current delete-then-copy path.
This idea came up during the investigation in https://github.com/dotnet/msbuild/issues/12927#issuecomment-4770589614.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.