Skip to content

Fix SingleConsumerUnboundedChannel WaitToReadAsync returning exception instead of false#125745

Open
Copilot wants to merge 3 commits intomainfrom
copilot/fix-waittoreadasync-exception
Open

Fix SingleConsumerUnboundedChannel WaitToReadAsync returning exception instead of false#125745
Copilot wants to merge 3 commits intomainfrom
copilot/fix-waittoreadasync-exception

Conversation

Copy link
Contributor

Copilot AI commented Mar 18, 2026

Description

SingleConsumerUnboundedChannel.WaitToReadAsync throws ChannelClosedException instead of returning false when a prior ReadAsync was cancelled and the channel is then completed normally.

In TryComplete, the error variable is mutated by CreateInvalidCompletionException when completing the blocked reader, then the now-non-null error is incorrectly propagated to the waiting reader:

// Before: mutates shared `error` variable
error = ChannelUtilities.CreateInvalidCompletionException(error); // null → ChannelClosedException
blockedReader.TrySetException(error);

// Later, `error` is no longer null, so waitingReader gets an exception instead of `false`
if (error is not null)
    waitingReader.TrySetException(error); // Bug: should have taken the else branch

Fix: inline the call so error is never reassigned.

blockedReader.TrySetException(ChannelUtilities.CreateInvalidCompletionException(error));

Adds a regression test covering the exact sequence: ReadAsync cancelled → WaitToReadAsyncComplete() → expect false.


📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.

…ception 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>
Copilot AI changed the title [WIP] [ISSUE-123] Fix WaitToReadAsync exception handling Fix SingleConsumerUnboundedChannel WaitToReadAsync returning exception instead of false Mar 18, 2026
Copilot AI requested a review from stephentoub March 18, 2026 20:40
@stephentoub stephentoub marked this pull request as ready for review March 18, 2026 21:10
Copilot AI review requested due to automatic review settings March 18, 2026 21:10
@stephentoub stephentoub enabled auto-merge (squash) March 18, 2026 21:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes SingleConsumerUnboundedChannel.WaitToReadAsync incorrectly faulting with ChannelClosedException (instead of returning false) after a prior cancellable ReadAsync was canceled and the channel is then completed successfully.

Changes:

  • Prevent TryComplete from mutating the shared error variable when completing a blocked reader, so waiting readers observe the correct completion state.
  • Add a regression test covering the canceled-ReadAsyncWaitToReadAsync → normal Complete() sequence.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/libraries/System.Threading.Channels/src/System/Threading/Channels/SingleConsumerUnboundedChannel.cs Avoids reassigning error when completing a blocked reader, preventing incorrect exception propagation to a waiting reader.
src/libraries/System.Threading.Channels/tests/UnboundedChannelTests.cs Adds regression coverage for WaitToReadAsync returning false after normal completion following a canceled ReadAsync.

You can also share your feedback on Copilot code review. Take the survey.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-threading-channels
See info in area-owners.md if you want to be subscribed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SingleConsumerUnboundedChannel WaitToReadAsync may complete with exception when it should return false

3 participants