Skip to content

fix: IOException thrown issue from HtmlPostProcessor #10637

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

filzrev
Copy link
Contributor

@filzrev filzrev commented Apr 17, 2025

This PR intended to fix #8654.
And contains following changes.

1. Add retry logics when HtmlPostProcessor throw IOException

Add retry logics to confirm behaviors. (Retry 3-times with delay 500ms/1000ms/1500ms 0ms/500ms/1000ms)
I don't sure this retry resolve reported issues though.
But it make possible to isolate the problem. file locking problem is transient issue or not.

2. Add additional logging when IOException is thrown
Add logics to find processes that lock target file by using Win32 APIs. and add warnings.
See: https://github.com/dotnet/runtime/issues/109927 for details.

It can detect when file is locked by external process (e.g. Windows Defender) or locked by self process.

@MartyIX
Copy link

MartyIX commented Apr 17, 2025

Thank you for working on this!

@VaclavElias
Copy link
Contributor

Thanks for looking into this.

@MartyIX
Copy link

MartyIX commented May 3, 2025

(Another try to generate my API doc and this time I disabled _gitContribute and it does not affect the result whatsoever. 2 successful attempts out of like 10.)

@yufeih yufeih requested a review from Copilot May 21, 2025 09:28
Copy link

@Copilot 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

This PR is intended to address an IOException issue from the HtmlPostProcessor by adding retry logic and additional logging to diagnose file locking problems.

  • Introduces retry logic (3 attempts with increasing delays) for file creation in ManifestFileWriter.cs.
  • Adds a new FileLockCheck.cs file that leverages Win32 APIs to detect processes locking a file.
  • Adds a new warning code (LockedFile) to support the additional logging and updates the project file to allow unsafe code blocks.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/Docfx.Common/Loggers/WarningCodes.cs New warning constant for file locking detection
src/Docfx.Common/FileLockCheck.cs New file for detecting processes locking a file using Win32 APIs
src/Docfx.Common/FileAbstractLayer/ManifestFileWriter.cs Implemented retry logic on file creation with added logging
src/Docfx.Common/Docfx.Common.csproj Enabled unsafe code blocks

Comment on lines 52 to 74
Retry:
try
{
Directory.CreateDirectory(
Path.Combine(_manifestFolder, file.RemoveWorkingFolder().GetDirectoryPath()));
var result = File.Create(Path.Combine(_manifestFolder, file.RemoveWorkingFolder()));
var fileStream = File.Create(path);
entry.LinkToPath = null;
return result;
return fileStream;
}
else
catch (IOException e) when ((e.HResult & 0x0000FFFF) == 32) // ERROR_SHARING_VIOLATION: 0x80070020
{
var path = Path.Combine(OutputFolder, file.RemoveWorkingFolder());
Directory.CreateDirectory(Path.GetDirectoryName(path));
var result = File.Create(path);
entry.LinkToPath = path;
return result;
// If retry failed 3 times. throw exception
if (++retryCount > 3)
throw;

var sleepDelay = 500 * retryCount;

var message = FileLockCheck.GetLockingProcessNames(path);
if (string.IsNullOrEmpty(message))
message = "File is locked by other process";

Logger.LogWarning($"{message}. Retry after {sleepDelay}[ms]", file: path, code: WarningCodes.Build.LockedFile);
Thread.Sleep(500 * retryCount);
goto Retry;
Copy link
Preview

Copilot AI May 21, 2025

Choose a reason for hiding this comment

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

[nitpick] Consider refactoring the retry logic to use a loop structure instead of a goto statement to improve code readability and maintainability.

Copilot uses AI. Check for mistakes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I know using goto statement is not recommended generally.
But it's more readable for simple retry patterns.
(And for complex retry scenario. It's better to use library (e.g. Polly) )

@filzrev filzrev force-pushed the fix-issue-8654 branch 2 times, most recently from 7464aff to 8101b80 Compare May 27, 2025 11:02
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.

[Bug] System.IO.IOException: The process cannot access the file
3 participants