From 8dd6bc401748d8a5e6606c6594b107a102ebc5bc Mon Sep 17 00:00:00 2001 From: Luke Bakken Date: Wed, 19 Mar 2025 12:11:05 -0700 Subject: [PATCH] Ensure that disposable instances are always disposed. Fixes #1808 (hopefully) --- .../Impl/AutorecoveringChannel.cs | 10 +++++-- .../Impl/AutorecoveringConnection.cs | 16 +++++++---- projects/RabbitMQ.Client/Impl/Channel.cs | 27 ++++++++++++++----- projects/RabbitMQ.Client/Impl/Connection.cs | 9 ++++++- projects/RabbitMQ.Client/InternalConstants.cs | 1 + 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/projects/RabbitMQ.Client/Impl/AutorecoveringChannel.cs b/projects/RabbitMQ.Client/Impl/AutorecoveringChannel.cs index 8cfb9553e..0ea8a2699 100644 --- a/projects/RabbitMQ.Client/Impl/AutorecoveringChannel.cs +++ b/projects/RabbitMQ.Client/Impl/AutorecoveringChannel.cs @@ -283,11 +283,17 @@ public async ValueTask DisposeAsync() await this.AbortAsync() .ConfigureAwait(false); } - - _recordedConsumerTags.Clear(); } finally { + try + { + _recordedConsumerTags.Clear(); + } + catch + { + } + _disposed = true; } } diff --git a/projects/RabbitMQ.Client/Impl/AutorecoveringConnection.cs b/projects/RabbitMQ.Client/Impl/AutorecoveringConnection.cs index b3a967a05..817bf0101 100644 --- a/projects/RabbitMQ.Client/Impl/AutorecoveringConnection.cs +++ b/projects/RabbitMQ.Client/Impl/AutorecoveringConnection.cs @@ -296,11 +296,6 @@ public async ValueTask DisposeAsync() { await _innerConnection.DisposeAsync() .ConfigureAwait(false); - - _channels.Clear(); - _recordedEntitiesSemaphore.Dispose(); - _channelsSemaphore.Dispose(); - _recoveryCancellationTokenSource.Dispose(); } catch (OperationInterruptedException) { @@ -308,6 +303,17 @@ await _innerConnection.DisposeAsync() } finally { + try + { + _channels.Clear(); + _recordedEntitiesSemaphore.Dispose(); + _channelsSemaphore.Dispose(); + _recoveryCancellationTokenSource.Dispose(); + } + catch + { + } + _disposed = true; } } diff --git a/projects/RabbitMQ.Client/Impl/Channel.cs b/projects/RabbitMQ.Client/Impl/Channel.cs index d8e3ef09a..b573d30e2 100644 --- a/projects/RabbitMQ.Client/Impl/Channel.cs +++ b/projects/RabbitMQ.Client/Impl/Channel.cs @@ -573,15 +573,23 @@ protected virtual void Dispose(bool disposing) this.AbortAsync().GetAwaiter().GetResult(); } - _serverOriginatedChannelCloseTcs?.Task.Wait(TimeSpan.FromSeconds(5)); + _serverOriginatedChannelCloseTcs?.Task.Wait(InternalConstants.DefaultChannelDisposeTimeout); ConsumerDispatcher.Dispose(); - _rpcSemaphore.Dispose(); - _confirmSemaphore.Dispose(); + _outstandingPublisherConfirmationsRateLimiter?.Dispose(); } finally { + try + { + _rpcSemaphore.Dispose(); + _confirmSemaphore.Dispose(); + } + catch + { + } + _disposed = true; } } @@ -622,13 +630,11 @@ await this.AbortAsync() if (_serverOriginatedChannelCloseTcs is not null) { - await _serverOriginatedChannelCloseTcs.Task.WaitAsync(TimeSpan.FromSeconds(5)) + await _serverOriginatedChannelCloseTcs.Task.WaitAsync(InternalConstants.DefaultChannelDisposeTimeout) .ConfigureAwait(false); } ConsumerDispatcher.Dispose(); - _rpcSemaphore.Dispose(); - _confirmSemaphore.Dispose(); if (_outstandingPublisherConfirmationsRateLimiter is not null) { @@ -638,6 +644,15 @@ await _outstandingPublisherConfirmationsRateLimiter.DisposeAsync() } finally { + try + { + _rpcSemaphore.Dispose(); + _confirmSemaphore.Dispose(); + } + catch + { + } + _disposed = true; } } diff --git a/projects/RabbitMQ.Client/Impl/Connection.cs b/projects/RabbitMQ.Client/Impl/Connection.cs index b2c271cc9..f661669af 100644 --- a/projects/RabbitMQ.Client/Impl/Connection.cs +++ b/projects/RabbitMQ.Client/Impl/Connection.cs @@ -550,7 +550,14 @@ await _channel0.DisposeAsync() } finally { - _mainLoopCts.Dispose(); + try + { + _mainLoopCts.Dispose(); + } + catch + { + } + _disposed = true; } } diff --git a/projects/RabbitMQ.Client/InternalConstants.cs b/projects/RabbitMQ.Client/InternalConstants.cs index 105ce297b..552062b18 100644 --- a/projects/RabbitMQ.Client/InternalConstants.cs +++ b/projects/RabbitMQ.Client/InternalConstants.cs @@ -37,6 +37,7 @@ internal static class InternalConstants { internal static readonly TimeSpan DefaultConnectionAbortTimeout = TimeSpan.FromSeconds(5); internal static readonly TimeSpan DefaultConnectionCloseTimeout = TimeSpan.FromSeconds(30); + internal static readonly TimeSpan DefaultChannelDisposeTimeout = TimeSpan.FromSeconds(5); /// /// Largest message size, in bytes, allowed in RabbitMQ.