From b10fec565eb131d0b8c240104b3b15af961e36dc Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sun, 29 Mar 2026 18:11:27 -0300 Subject: [PATCH 1/2] Fix anti-stuck not working when there was zero progress --- Knossos.NET/Classes/ThrottledStream.cs | 11 +++++-- .../Templates/Tasks/DownloadFile.cs | 32 ++++++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Knossos.NET/Classes/ThrottledStream.cs b/Knossos.NET/Classes/ThrottledStream.cs index 93d1cbfa..e1dbb6ea 100644 --- a/Knossos.NET/Classes/ThrottledStream.cs +++ b/Knossos.NET/Classes/ThrottledStream.cs @@ -1,6 +1,7 @@ -using System.Threading; +using System; using System.IO; -using System; +using System.Threading; +using System.Threading.Tasks; namespace Knossos.NET.Classes @@ -150,5 +151,11 @@ public override long Seek(long offset, SeekOrigin origin) { return stream.Seek(offset, origin); } + + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + { + Limit(buffer.Length); + return stream.ReadAsync(buffer, cancellationToken); + } } } diff --git a/Knossos.NET/ViewModels/Templates/Tasks/DownloadFile.cs b/Knossos.NET/ViewModels/Templates/Tasks/DownloadFile.cs index 5e7b341b..7b1cb12e 100644 --- a/Knossos.NET/ViewModels/Templates/Tasks/DownloadFile.cs +++ b/Knossos.NET/ViewModels/Templates/Tasks/DownloadFile.cs @@ -238,7 +238,32 @@ private async Task Download(Uri downloadUrl, string destinationFilePath, F throw new TaskCanceledException(); } - var bytesRead = await contentStream.ReadAsync(buffer); + int bytesRead = 0; + if (Knossos.globalSettings.antiStuck) + { + //If there is zero progress, cancel (throws exception) + using var readTimeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(ANTI_STUCK_CHECK_SECONDS)); + using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource!.Token, readTimeoutCts.Token); + try + { + bytesRead = await contentStream.ReadAsync(buffer.AsMemory(), linkedCts.Token); + } + catch (OperationCanceledException) + { + if (readTimeoutCts.IsCancellationRequested) + { + Log.Add(Log.LogSeverity.Warning, "TaskItemViewModel.Download", + $"[ANTI-STUCK] Mirror {CurrentMirror ?? downloadUrl.Host} is stuck. " + + "Changing to a diferent mirror..."); + } + return false; + } + } + else + { + bytesRead = await contentStream.ReadAsync(buffer.AsMemory()); + } + if (bytesRead == 0) { isMoreToRead = false; @@ -300,6 +325,11 @@ private async Task Download(Uri downloadUrl, string destinationFilePath, F stopwatch.Reset(); return true; } + catch (OperationCanceledException) + { + //cancel requested, do not log + return false; + } catch (Exception ex) { Log.Add(Log.LogSeverity.Error, "TaskItemViewModel.Download", ex); From 32c0abc433528b671e368384d3ec99c2f7ebe5cd Mon Sep 17 00:00:00 2001 From: Salvador Cipolla Date: Sun, 29 Mar 2026 18:17:45 -0300 Subject: [PATCH 2/2] Add the manual CT to non anti-stuck reads --- Knossos.NET/ViewModels/Templates/Tasks/DownloadFile.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Knossos.NET/ViewModels/Templates/Tasks/DownloadFile.cs b/Knossos.NET/ViewModels/Templates/Tasks/DownloadFile.cs index 7b1cb12e..d7c9bcf4 100644 --- a/Knossos.NET/ViewModels/Templates/Tasks/DownloadFile.cs +++ b/Knossos.NET/ViewModels/Templates/Tasks/DownloadFile.cs @@ -261,7 +261,7 @@ private async Task Download(Uri downloadUrl, string destinationFilePath, F } else { - bytesRead = await contentStream.ReadAsync(buffer.AsMemory()); + bytesRead = await contentStream.ReadAsync(buffer.AsMemory(), cancellationTokenSource!.Token); } if (bytesRead == 0) @@ -325,11 +325,6 @@ private async Task Download(Uri downloadUrl, string destinationFilePath, F stopwatch.Reset(); return true; } - catch (OperationCanceledException) - { - //cancel requested, do not log - return false; - } catch (Exception ex) { Log.Add(Log.LogSeverity.Error, "TaskItemViewModel.Download", ex);