From 1992ff23eb47fe21780708119edf119a433cf09d Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Thu, 9 Jan 2025 13:15:17 +0100 Subject: [PATCH] Put two Task.Yield calls into place to make sure the receive loop in WebSocketGremlinqClient won't get stuck. --- .../Factory/WebSocketGremlinqClientFactory.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Providers.Core/Factory/WebSocketGremlinqClientFactory.cs b/src/Providers.Core/Factory/WebSocketGremlinqClientFactory.cs index df0e9ea70..4f729cb36 100644 --- a/src/Providers.Core/Factory/WebSocketGremlinqClientFactory.cs +++ b/src/Providers.Core/Factory/WebSocketGremlinqClientFactory.cs @@ -128,12 +128,21 @@ public async IAsyncEnumerator> GetAsyncEnumerator(Cancellatio if (await new ValueTask?>(this, 0).ConfigureAwait(false) is { } union) { if (union.TryGetResponse(out var response)) + { + // Since the below yield return is what effectively yields control back to user code, + // the receive loop may stall if user code blocks. Although technically not Gremlinq's + // fault, we take this measure. + await Task.Yield(); + yield return response; + } else if (union.TryGetQueue(out var semaphore, out var queue)) { while (true) { - await semaphore.WaitAsync(ct).ConfigureAwait(false); + await semaphore + .WaitAsync(ct) + .ConfigureAwait(false); if (queue.TryDequeue(out var queuedResponse)) { @@ -155,6 +164,9 @@ await _client } else { + // See above. + await Task.Yield(); + yield return queuedResponse; if (queuedResponse.Status.Code != PartialContent)