From fdf7a0492d010bc1f2cad2762a4b1cad66d19254 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 20:08:01 +0000 Subject: [PATCH 1/3] Initial plan From 1152a1cd931d84910fc5c7b6b9cfcd1df589b77c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 20:38:05 +0000 Subject: [PATCH 2/3] Fix SingleConsumerUnboundedChannel WaitToReadAsync completing with exception instead of false In TryComplete, the error variable was mutated by CreateInvalidCompletionException for the blocked reader, causing the waiting reader to incorrectly receive a ChannelClosedException instead of returning false when the channel was completed successfully. Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- .../Channels/SingleConsumerUnboundedChannel.cs | 3 +-- .../tests/UnboundedChannelTests.cs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/SingleConsumerUnboundedChannel.cs b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/SingleConsumerUnboundedChannel.cs index 969249384ac1de..ddc3e7b11f25f1 100644 --- a/src/libraries/System.Threading.Channels/src/System/Threading/Channels/SingleConsumerUnboundedChannel.cs +++ b/src/libraries/System.Threading.Channels/src/System/Threading/Channels/SingleConsumerUnboundedChannel.cs @@ -254,8 +254,7 @@ public override bool TryComplete(Exception? error) // Complete a blocked reader if necessary if (blockedReader is not null) { - error = ChannelUtilities.CreateInvalidCompletionException(error); - blockedReader.TrySetException(error); + blockedReader.TrySetException(ChannelUtilities.CreateInvalidCompletionException(error)); } // Complete a waiting reader if necessary. (We really shouldn't have both a blockedReader diff --git a/src/libraries/System.Threading.Channels/tests/UnboundedChannelTests.cs b/src/libraries/System.Threading.Channels/tests/UnboundedChannelTests.cs index 3ca8cc5741e886..d976f9a2c8afab 100644 --- a/src/libraries/System.Threading.Channels/tests/UnboundedChannelTests.cs +++ b/src/libraries/System.Threading.Channels/tests/UnboundedChannelTests.cs @@ -242,6 +242,23 @@ public async Task MultipleReaders_CancelsPreviousReader() Assert.Equal(42, await t2); } + [Fact] + public async Task WaitToReadAsync_ReturnsFalse_WhenReadAsyncWasCancelledAndChannelCompleted() + { + Channel c = CreateChannel(); + + using var cts = new CancellationTokenSource(); + ValueTask readTask = c.Reader.ReadAsync(cts.Token); + cts.Cancel(); + await Assert.ThrowsAnyAsync(async () => await readTask); + + ValueTask waitTask = c.Reader.WaitToReadAsync(CancellationToken.None); + + c.Writer.Complete(); + + Assert.False(await waitTask); + } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsMultithreadingSupported))] public void Stress_TryWrite_TryRead() { From ac83427bba0385ad4f36f65d36592ba225ca641b Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Wed, 18 Mar 2026 17:14:38 -0400 Subject: [PATCH 3/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../System.Threading.Channels/tests/UnboundedChannelTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Threading.Channels/tests/UnboundedChannelTests.cs b/src/libraries/System.Threading.Channels/tests/UnboundedChannelTests.cs index d976f9a2c8afab..ae5cccb05a73ac 100644 --- a/src/libraries/System.Threading.Channels/tests/UnboundedChannelTests.cs +++ b/src/libraries/System.Threading.Channels/tests/UnboundedChannelTests.cs @@ -243,7 +243,7 @@ public async Task MultipleReaders_CancelsPreviousReader() } [Fact] - public async Task WaitToReadAsync_ReturnsFalse_WhenReadAsyncWasCancelledAndChannelCompleted() + public async Task WaitToReadAsync_ReturnsFalse_WhenReadAsyncWasCanceledAndChannelCompleted() { Channel c = CreateChannel();