diff --git a/build/Version.props b/build/Version.props index 18219375ac..a6146fedf0 100644 --- a/build/Version.props +++ b/build/Version.props @@ -3,7 +3,7 @@ - 6.11.3 + 6.11.4 5.3.0 10.10.0 0.2.0 diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs index eff31ebb25..f0edb6fc09 100644 --- a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs +++ b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs @@ -140,9 +140,9 @@ sealed class Configuration : IConfiguration readonly SemaphoreSlim semaphore; /// - /// The that is triggered when is called. + /// The that is triggered when is called. /// - readonly CancellationTokenSource disposeCts; + readonly CancellationTokenSource stoppingCts; /// /// The culmination of all upload file transfer callbacks. @@ -186,7 +186,7 @@ public Configuration( this.sessionConfiguration = sessionConfiguration ?? throw new ArgumentNullException(nameof(sessionConfiguration)); semaphore = new SemaphoreSlim(1, 1); - disposeCts = new CancellationTokenSource(); + stoppingCts = new CancellationTokenSource(); uploadTasks = Task.CompletedTask; } @@ -194,8 +194,7 @@ public Configuration( public void Dispose() { semaphore.Dispose(); - disposeCts.Cancel(); - disposeCts.Dispose(); + stoppingCts.Dispose(); } /// @@ -310,7 +309,7 @@ string GetFileSha() var originalSha = GetFileSha(); - var disposeToken = disposeCts.Token; + var disposeToken = stoppingCts.Token; var fileTicket = fileTransferService.CreateDownload( new FileDownloadProvider( () => @@ -472,7 +471,7 @@ void WriteImpl() try { var fileTicket = fileTransferService.CreateUpload(FileUploadStreamKind.ForSynchronousIO); - var uploadCancellationToken = disposeCts.Token; + var uploadCancellationToken = stoppingCts.Token; async Task UploadHandler() { await using (fileTicket) @@ -491,7 +490,7 @@ async Task UploadHandler() void WriteCallback() { logger.LogTrace("Running synchronous write..."); - success = synchronousIOManager.WriteFileChecked(path, uploadStream, ref fileHash, cancellationToken); + success = synchronousIOManager.WriteFileChecked(path, uploadStream, ref fileHash, uploadCancellationToken); logger.LogTrace("Finished write {un}successfully!", success ? String.Empty : "un"); } @@ -511,9 +510,9 @@ void WriteCallback() logger.LogTrace("Kicking off write callback"); if (systemIdentity == null) - await Task.Factory.StartNew(WriteCallback, cancellationToken, DefaultIOManager.BlockingTaskCreationOptions, TaskScheduler.Current); + await Task.Factory.StartNew(WriteCallback, uploadCancellationToken, DefaultIOManager.BlockingTaskCreationOptions, TaskScheduler.Current); else - await systemIdentity.RunImpersonated(WriteCallback, cancellationToken); + await systemIdentity.RunImpersonated(WriteCallback, uploadCancellationToken); } if (!success) @@ -534,8 +533,24 @@ void WriteCallback() Path = configurationRelativePath, }; - lock (disposeCts) - uploadTasks = Task.WhenAll(uploadTasks, UploadHandler()); + lock (stoppingCts) + { + async Task ChainUploadTasks() + { + var oldUploadTask = uploadTasks; + var newUploadTask = UploadHandler(); + try + { + await oldUploadTask; + } + finally + { + await newUploadTask; + } + } + + uploadTasks = ChainUploadTasks(); + } } catch (UnauthorizedAccessException) { @@ -609,7 +624,24 @@ void WriteCallback() public Task StartAsync(CancellationToken cancellationToken) => EnsureDirectories(cancellationToken); /// - public Task StopAsync(CancellationToken cancellationToken) => EnsureDirectories(cancellationToken); + public async Task StopAsync(CancellationToken cancellationToken) + { + await EnsureDirectories(cancellationToken); + + stoppingCts.Cancel(); + try + { + await uploadTasks; + } + catch (OperationCanceledException ex) + { + logger.LogDebug(ex, "One or more uploads/downloads were aborted!"); + } + catch (Exception ex) + { + logger.LogError(ex, "Error awaiting upload tasks!"); + } + } /// public ValueTask HandleEvent(EventType eventType, IEnumerable parameters, bool deploymentPipeline, CancellationToken cancellationToken)