Skip to content

[Backport v1.5] fix(streams): prevent race condition in ChannelSource on channel completion#7951

Merged
Aaronontheweb merged 1 commit intoakkadotnet:v1.5from
Aaronontheweb:backport/v1.5-channel-source-race-fix
Nov 25, 2025
Merged

[Backport v1.5] fix(streams): prevent race condition in ChannelSource on channel completion#7951
Aaronontheweb merged 1 commit intoakkadotnet:v1.5from
Aaronontheweb:backport/v1.5-channel-source-race-fix

Conversation

@Aaronontheweb
Copy link
Member

Summary

Backport of #7941 to v1.5 branch.

  • Prevents race condition in ChannelSource when channel completion occurs during streaming

Original PR: #7941

@Aaronontheweb Aaronontheweb force-pushed the backport/v1.5-channel-source-race-fix branch from 36c9f1b to 008e451 Compare November 25, 2025 17:23
…letion (akkadotnet#7941)

* fix(streams): prevent race condition in ChannelSource on channel completion (akkadotnet#7940)

Fixed a race condition in ChannelSourceLogic that caused intermittent
NullReferenceException when completing a ChannelWriter while the stream
was waiting for data.

The issue occurred because two async callbacks could fire simultaneously
when the channel writer completed:
1. The _reader.Completion continuation → OnReaderComplete → CompleteStage
2. The WaitToReadAsync continuation → OnValueRead(false) → CompleteStage

Both paths could pass the IsStageCompleted check before either completed
the stage, leading to concurrent access of stage internals.

The fix adds an atomic flag (_completing) using Interlocked.Exchange to
ensure only one completion path ever executes. This is applied to:
- OnReaderComplete - channel completion callback
- OnValueRead - when data is not available
- OnValueReadFailure - when read fails
- OnPull - synchronous completion path

* refactor: use CompareExchange instead of Exchange for atomic flag

CompareExchange is more semantically correct - it only sets the value
if it's currently 0, rather than unconditionally setting it.
@Aaronontheweb Aaronontheweb force-pushed the backport/v1.5-channel-source-race-fix branch from 008e451 to 3720c05 Compare November 25, 2025 17:25
@Aaronontheweb Aaronontheweb merged commit 70695d9 into akkadotnet:v1.5 Nov 25, 2025
7 of 11 checks passed
@Aaronontheweb Aaronontheweb added this to the 1.5.56 milestone Nov 25, 2025
@Aaronontheweb Aaronontheweb deleted the backport/v1.5-channel-source-race-fix branch November 25, 2025 18:28
@Aaronontheweb Aaronontheweb removed this from the 1.5.56 milestone Nov 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant