Skip to content

Fix race condition in QueueSink causing async enumerable timeout#7973

Merged
Aaronontheweb merged 2 commits intoakkadotnet:devfrom
Aaronontheweb:claude-wt-AsyncEnumerableSpec.RunAsAsyncEnumerable_Throws_on_Abrupt_Stream_termination
Dec 22, 2025
Merged

Fix race condition in QueueSink causing async enumerable timeout#7973
Aaronontheweb merged 2 commits intoakkadotnet:devfrom
Aaronontheweb:claude-wt-AsyncEnumerableSpec.RunAsAsyncEnumerable_Throws_on_Abrupt_Stream_termination

Conversation

@Aaronontheweb
Copy link
Member

Summary

Fixed a timing-dependent race condition where RunAsAsyncEnumerable would timeout when the materializer shut down while a PullAsync() request was pending.

Changes

  • Modified QueueSink.Logic.PostStop() to properly complete any pending TaskCompletionSource stored in _currentRequest with a StreamDetachedException before shutting down
  • This prevents orphaned Tasks that would never complete

Issue

This resolves intermittent test failures in AsyncEnumerableSpec.RunAsAsyncEnumerable_Throws_on_Abrupt_Stream_termination where the test would hang waiting for an exception that never arrived.

Root Cause

When the materializer shut down abruptly, the PostStop() method only set up a callback handler for future pull requests but didn't clean up already-pending requests waiting for data. The pending TaskCompletionSource in _currentRequest would remain incomplete, causing the async enumerable to hang indefinitely.

Testing

  • ✅ Previously failing test now passes consistently (10/10 runs)
  • ✅ All 13 tests in AsyncEnumerableSpec suite pass
  • ✅ No regressions introduced

Fixed a timing-dependent race condition where RunAsAsyncEnumerable would timeout when the materializer shut down while a PullAsync() request was pending.

The QueueSink.Logic.PostStop() method now properly completes any pending TaskCompletionSource stored in _currentRequest with a StreamDetachedException before shutting down, preventing orphaned Tasks that would never complete.

This resolves intermittent test failures in AsyncEnumerableSpec.RunAsAsyncEnumerable_Throws_on_Abrupt_Stream_termination where the test would hang waiting for an exception that never arrived.
public override void PostStop()
{
// Complete any pending request before shutting down to prevent orphaned Tasks
if (_currentRequest.HasValue)
Copy link
Member Author

Choose a reason for hiding this comment

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

Need to do this otherwise the IAsyncEnumerable hangs on the _currentRequest value

@Aaronontheweb Aaronontheweb enabled auto-merge (squash) December 22, 2025 18:11
@Aaronontheweb Aaronontheweb merged commit d08c433 into akkadotnet:dev Dec 22, 2025
11 checks passed
Arkatufus pushed a commit to Arkatufus/akka.net that referenced this pull request Jan 7, 2026
…adotnet#7973)

Fixed a timing-dependent race condition where RunAsAsyncEnumerable would timeout when the materializer shut down while a PullAsync() request was pending.

The QueueSink.Logic.PostStop() method now properly completes any pending TaskCompletionSource stored in _currentRequest with a StreamDetachedException before shutting down, preventing orphaned Tasks that would never complete.

This resolves intermittent test failures in AsyncEnumerableSpec.RunAsAsyncEnumerable_Throws_on_Abrupt_Stream_termination where the test would hang waiting for an exception that never arrived.
Aaronontheweb added a commit that referenced this pull request Jan 8, 2026
Fixed a timing-dependent race condition where RunAsAsyncEnumerable would timeout when the materializer shut down while a PullAsync() request was pending.

The QueueSink.Logic.PostStop() method now properly completes any pending TaskCompletionSource stored in _currentRequest with a StreamDetachedException before shutting down, preventing orphaned Tasks that would never complete.

This resolves intermittent test failures in AsyncEnumerableSpec.RunAsAsyncEnumerable_Throws_on_Abrupt_Stream_termination where the test would hang waiting for an exception that never arrived.
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.

1 participant