Skip to content

Commit

Permalink
fix: only allow one duplication at a time
Browse files Browse the repository at this point in the history
Prevent simultaneous duplications from racing on a delete, causing potential file not found errors.
  • Loading branch information
anna-is-cute committed Aug 25, 2024
1 parent 3577f6f commit d0c32a2
Showing 1 changed file with 8 additions and 2 deletions.
10 changes: 8 additions & 2 deletions DownloadTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ internal class DownloadTask : IDisposable {
private ConcurrentDeque<Measurement> Entries { get; } = new();
private Util.SentryTransaction? Transaction { get; set; }
private bool SupportsHardLinks { get; set; }
private SemaphoreSlim DuplicateMutex { get; } = new(1, 1);

/// <summary>
/// A mapping of existing file paths to their hashes. Paths are relative.
Expand Down Expand Up @@ -123,6 +124,7 @@ public void Dispose() {
this._disposed = true;
GC.SuppressFinalize(this);
this.CancellationToken.Dispose();
this.DuplicateMutex.Dispose();
}

internal Task Start() {
Expand Down Expand Up @@ -582,7 +584,7 @@ await Plugin.Resilience.ExecuteAsync(
var gamePaths = neededFiles.Files.Files[hash];
var outputPaths = GetOutputPaths(gamePaths);
await DuplicateFile(filesPath, outputPaths, joined);
await this.DuplicateFile(filesPath, outputPaths, joined);
this.StateData += 1;
}
Expand Down Expand Up @@ -754,6 +756,8 @@ private static string[] GetOutputPaths(IReadOnlyCollection<List<string?>> files)
}

private async Task DuplicateFile(string filesDir, IEnumerable<string> outputPaths, string path) {
using var guard = await SemaphoreGuard.WaitAsync(this.DuplicateMutex, this.CancellationToken.Token);

if (!this.SupportsHardLinks) {
// If hard links aren't supported, copy the path to the first output
// path.
Expand Down Expand Up @@ -788,6 +792,8 @@ private async Task DuplicateFile(string filesDir, IEnumerable<string> outputPath
await DuplicateInner(outputPath);
}

return;

async Task DuplicateInner(string dest) {
dest = Path.Join(filesDir, dest);
if (path.Equals(dest, StringComparison.InvariantCultureIgnoreCase)) {
Expand Down Expand Up @@ -896,7 +902,7 @@ await resp.Content.ReadAsStreamAsync(this.CancellationToken.Token),
);

Duplicate:
await DuplicateFile(filesPath, outputPaths, validPath);
await this.DuplicateFile(filesPath, outputPaths, validPath);

this.StateData += 1;
}
Expand Down

0 comments on commit d0c32a2

Please sign in to comment.