1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-07-23 18:05:43 +00:00

Fix issue where SemaphoreSlim is released twice in RateLimitGate (#210)

This commit is contained in:
Jonnern 2024-08-28 12:25:09 +02:00 committed by GitHub
parent d89c2bde94
commit 42003a0247
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -32,21 +32,29 @@ namespace CryptoExchange.Net.RateLimiting
{ {
_name = name; _name = name;
_guards = new ConcurrentBag<IRateLimitGuard>(); _guards = new ConcurrentBag<IRateLimitGuard>();
_semaphore = new SemaphoreSlim(1); _semaphore = new SemaphoreSlim(1, 1);
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task<CallResult> ProcessAsync(ILogger logger, int itemId, RateLimitItemType type, RequestDefinition definition, string host, string? apiKey, int requestWeight, RateLimitingBehaviour rateLimitingBehaviour, CancellationToken ct) public async Task<CallResult> ProcessAsync(ILogger logger, int itemId, RateLimitItemType type, RequestDefinition definition, string host, string? apiKey, int requestWeight, RateLimitingBehaviour rateLimitingBehaviour, CancellationToken ct)
{ {
await _semaphore.WaitAsync(ct).ConfigureAwait(false); await _semaphore.WaitAsync(ct).ConfigureAwait(false);
bool release = true;
_waitingCount++; _waitingCount++;
try try
{ {
return await CheckGuardsAsync(_guards, logger, itemId, type, definition, host, apiKey, requestWeight, rateLimitingBehaviour, ct).ConfigureAwait(false); return await CheckGuardsAsync(_guards, logger, itemId, type, definition, host, apiKey, requestWeight, rateLimitingBehaviour, ct).ConfigureAwait(false);
} }
catch (TaskCanceledException)
{
// The semaphore has alraedy been released if the task was cancelled
release = false;
throw;
}
finally finally
{ {
_waitingCount--; _waitingCount--;
if (release)
_semaphore.Release(); _semaphore.Release();
} }
} }
@ -64,15 +72,22 @@ namespace CryptoExchange.Net.RateLimiting
CancellationToken ct) CancellationToken ct)
{ {
await _semaphore.WaitAsync(ct).ConfigureAwait(false); await _semaphore.WaitAsync(ct).ConfigureAwait(false);
bool release = true;
_waitingCount++; _waitingCount++;
try try
{ {
return await CheckGuardsAsync(new IRateLimitGuard[] { guard }, logger, itemId, type, definition, host, apiKey, 1, rateLimitingBehaviour, ct).ConfigureAwait(false); return await CheckGuardsAsync(new IRateLimitGuard[] { guard }, logger, itemId, type, definition, host, apiKey, 1, rateLimitingBehaviour, ct).ConfigureAwait(false);
} }
catch (TaskCanceledException)
{
// The semaphore has alraedy been released if the task was cancelled
release = false;
throw;
}
finally finally
{ {
_waitingCount--; _waitingCount--;
if (release)
_semaphore.Release(); _semaphore.Release();
} }
} }