diff options
author | Brennan Conroy <brecon@microsoft.com> | 2022-08-30 02:38:25 +0300 |
---|---|---|
committer | Brennan Conroy <brecon@microsoft.com> | 2022-08-30 02:38:25 +0300 |
commit | f265b5ab5df8e4e44fa3eaf75b1f2909a050351c (patch) | |
tree | 0172bfae1bb29a497ad76b773b7196ef67414e4a | |
parent | daed048f882dd2b19defa9647e4aefc4603e76f3 (diff) |
-rw-r--r-- | src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs | 6 | ||||
-rw-r--r-- | src/SignalR/server/Core/src/Internal/HubCallerClients.cs | 12 |
2 files changed, 12 insertions, 6 deletions
diff --git a/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs b/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs index 508a04bb40..7e0b3f86bb 100644 --- a/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs +++ b/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs @@ -324,9 +324,9 @@ internal sealed partial class DefaultHubDispatcher<THub> : HubDispatcher<THub> w if (hub.Clients is HubCallerClients hubCallerClients) { // Streaming invocations aren't involved with the semaphore. - // Setting this to 0 avoids potential client result calls from the streaming hub method + // Setting the semaphore released flag avoids potential client result calls from the streaming hub method // releasing the semaphore which would cause a SemaphoreFullException. - hubCallerClients.ShouldReleaseSemaphore = 0; + hubCallerClients.TrySetSemaphoreReleased(); } } @@ -415,7 +415,7 @@ internal sealed partial class DefaultHubDispatcher<THub> : HubDispatcher<THub> w { if (hub?.Clients is HubCallerClients hubCallerClients) { - wasSemaphoreReleased = Interlocked.CompareExchange(ref hubCallerClients.ShouldReleaseSemaphore, 0, 1) == 0; + wasSemaphoreReleased = !hubCallerClients.TrySetSemaphoreReleased(); } await CleanupInvocation(connection, hubMethodInvocationMessage, hubActivator, hub, scope); } diff --git a/src/SignalR/server/Core/src/Internal/HubCallerClients.cs b/src/SignalR/server/Core/src/Internal/HubCallerClients.cs index 8e6ec0fa0d..15d2c03660 100644 --- a/src/SignalR/server/Core/src/Internal/HubCallerClients.cs +++ b/src/SignalR/server/Core/src/Internal/HubCallerClients.cs @@ -9,7 +9,7 @@ internal sealed class HubCallerClients : IHubCallerClients private readonly IHubClients _hubClients; internal readonly ChannelBasedSemaphore _parallelInvokes; - internal int ShouldReleaseSemaphore = 1; + private int _shouldReleaseSemaphore = 1; // Client results don't work in OnConnectedAsync // This property is set by the hub dispatcher when those methods are being called @@ -90,6 +90,12 @@ internal sealed class HubCallerClients : IHubCallerClients return _hubClients.Users(userIds); } + // false if semaphore is being released by another caller, true if you own releasing the semaphore + internal bool TrySetSemaphoreReleased() + { + return Interlocked.CompareExchange(ref _shouldReleaseSemaphore, 0, 1) == 1; + } + private sealed class NoInvokeSingleClientProxy : ISingleClientProxy { private readonly ISingleClientProxy _proxy; @@ -125,9 +131,9 @@ internal sealed class HubCallerClients : IHubCallerClients { // Releases the Channel that is blocking pending invokes, which in turn can block the receive loop. // Because we are waiting for a result from the client we need to let the receive loop run otherwise we'll be blocked forever - var value = Interlocked.CompareExchange(ref _hubCallerClients.ShouldReleaseSemaphore, 0, 1); + var value = _hubCallerClients.TrySetSemaphoreReleased(); // Only release once, and we set ShouldReleaseSemaphore to 0 so the DefaultHubDispatcher knows not to call Release again - if (value == 1) + if (value) { _hubCallerClients._parallelInvokes.Release(); } |