Skip to content
This repository has been archived by the owner on Apr 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #9402 from wli3/port-2.1.3-Add-retry-when-Director…
Browse files Browse the repository at this point in the history
…y.Move

Port 2.1.3xx add retry when directory.move
  • Loading branch information
William Li authored Jun 1, 2018
2 parents 9e9fe6d + ea539c7 commit 42cd5fd
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 5 deletions.
31 changes: 31 additions & 0 deletions src/Microsoft.DotNet.Cli.Utils/FileAccessRetryer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.DotNet.Cli.Utils
Expand Down Expand Up @@ -47,5 +48,35 @@ public static class FileAccessRetrier
}
}
}

/// <summary>
/// Run Directory.Move and File.Move in Windows has a chance to get IOException with
/// HResult 0x80070005 due to Indexer. But this error is transient.
/// </summary>
internal static void RetryOnMoveAccessFailure(Action action)
{
const int ERROR_HRESULT_ACCESS_DENIED = unchecked((int)0x80070005);
int nextWaitTime = 10;
int remainRetry = 10;

while (true)
{
try
{
action();
break;
}
catch (IOException e) when (e.HResult == ERROR_HRESULT_ACCESS_DENIED)
{
Thread.Sleep(nextWaitTime);
nextWaitTime *= 2;
remainRetry--;
if (remainRetry == 0)
{
throw;
}
}
}
}
}
}
4 changes: 2 additions & 2 deletions src/dotnet/ShellShim/ShellShimRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public void RemoveShim(string commandName)
foreach (var file in GetShimFiles(commandName).Where(f => _fileSystem.File.Exists(f.Value)))
{
var tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
_fileSystem.File.Move(file.Value, tempPath);
FileAccessRetrier.RetryOnMoveAccessFailure(() => _fileSystem.File.Move(file.Value, tempPath));
files[file.Value] = tempPath;
}
}
Expand All @@ -137,7 +137,7 @@ public void RemoveShim(string commandName)
rollback: () => {
foreach (var kvp in files)
{
_fileSystem.File.Move(kvp.Value, kvp.Key);
FileAccessRetrier.RetryOnMoveAccessFailure(() => _fileSystem.File.Move(kvp.Value, kvp.Key));
}
});
}
Expand Down
3 changes: 2 additions & 1 deletion src/dotnet/ToolPackage/ToolPackageInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Xml.Linq;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.Tools;
using Microsoft.Extensions.EnvironmentAbstractions;
Expand Down Expand Up @@ -82,7 +83,7 @@ public IToolPackage InstallPackage(PackageId packageId,
}

Directory.CreateDirectory(packageRootDirectory.Value);
Directory.Move(stageDirectory.Value, packageDirectory.Value);
FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(stageDirectory.Value, packageDirectory.Value));
rollbackDirectory = packageDirectory.Value;

return new ToolPackageInstance(_store, packageId, version, packageDirectory);
Expand Down
5 changes: 3 additions & 2 deletions src/dotnet/ToolPackage/ToolPackageInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using NuGet.ProjectModel;
using NuGet.Versioning;
using Microsoft.DotNet.Cli.Utils;
using System.Threading;

namespace Microsoft.DotNet.ToolPackage
{
Expand Down Expand Up @@ -79,7 +80,7 @@ public void Uninstall()
// Use the staging directory for uninstall
// This prevents cross-device moves when temp is mounted to a different device
var tempPath = _store.GetRandomStagingDirectory().Value;
Directory.Move(PackageDirectory.Value, tempPath);
FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(PackageDirectory.Value, tempPath));
tempPackageDirectory = tempPath;
}

Expand Down Expand Up @@ -111,7 +112,7 @@ public void Uninstall()
if (tempPackageDirectory != null)
{
Directory.CreateDirectory(rootDirectory.Value);
Directory.Move(tempPackageDirectory, PackageDirectory.Value);
FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(tempPackageDirectory, PackageDirectory.Value));
}
});
}
Expand Down

0 comments on commit 42cd5fd

Please sign in to comment.