Skip to content

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.
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