Skip to content

Fix race condition in WriteLinesToFile transactional mode (#13323)#13477

Open
huulinhnguyen-dev wants to merge 8 commits intodotnet:mainfrom
huulinhnguyen-dev:dev/huulinhnguyen/issue13323_flaky_test_transactional
Open

Fix race condition in WriteLinesToFile transactional mode (#13323)#13477
huulinhnguyen-dev wants to merge 8 commits intodotnet:mainfrom
huulinhnguyen-dev:dev/huulinhnguyen/issue13323_flaky_test_transactional

Conversation

@huulinhnguyen-dev
Copy link
Copy Markdown
Contributor

Fixes #13323

Context

Concurrent parallel builds writing to the same file with Overwrite="true" and transactional mode could throw IOException: Cannot create a file when that file already exists. This happened because File.Move failed when another thread created the target file between the Replace check and the Move call.

Changes Made

  • In WriteLinesToFile.cs: when File.Move fails with IOException, retry using File.Replace since the target file now exists
  • In WriteLinesToFile_Tests.cs: rename TransactionalModePreservesAllDataTransactionalModeSucceedsWithConcurrentOverwrites to accurately reflect test behavior (Overwrite="true" means only the last writer survives, not all data)

Testing

Existing test TransactionalModeSucceedsWithConcurrentOverwrites covers the concurrent overwrite scenario with parallel MSBuild projects.

huulinhnguyen-dev and others added 6 commits April 1, 2026 13:50
Copilot AI review requested due to automatic review settings April 1, 2026 08:02
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a race in the built-in WriteLinesToFile task’s transactional overwrite path where concurrent writers could cause File.Move to fail with “file already exists”, by falling back to File.Replace when the destination appears mid-operation.

Changes:

  • Add a transactional overwrite recovery path: if File.Move fails and the destination now exists, retry via File.Replace with a small bounded retry loop.
  • Rename the flaky/misleading concurrent overwrite test to reflect actual Overwrite="true" semantics.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/Tasks/FileIO/WriteLinesToFile.cs Adds a File.Replace-based fallback when Move fails due to a concurrent create, improving reliability under parallel builds.
src/Tasks.UnitTests/WriteLinesToFile_Tests.cs Renames a test to better describe the concurrent overwrite behavior being validated.

@huulinhnguyen-dev huulinhnguyen-dev marked this pull request as draft April 1, 2026 08:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

@huulinhnguyen-dev huulinhnguyen-dev marked this pull request as ready for review April 2, 2026 08:13
@huulinhnguyen-dev huulinhnguyen-dev marked this pull request as draft April 2, 2026 09:30
@huulinhnguyen-dev huulinhnguyen-dev marked this pull request as ready for review April 2, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TransactionalModePreservesAllData test is flaky

2 participants