@@ -57,13 +57,14 @@ internal partial class Channel : IChannel, IRecoverable
57
57
private readonly RpcContinuationQueue _continuationQueue = new RpcContinuationQueue ( ) ;
58
58
59
59
private ShutdownEventArgs ? _closeReason ;
60
- public ShutdownEventArgs ? CloseReason => Volatile . Read ( ref _closeReason ) ;
60
+ private TaskCompletionSource < bool > ? _serverOriginatedChannelCloseTcs ;
61
61
62
62
internal readonly IConsumerDispatcher ConsumerDispatcher ;
63
63
64
64
private bool _disposedValue ;
65
65
private bool _isDisposing ;
66
- private readonly object _isDisposingLock = new ( ) ;
66
+
67
+ private readonly object _locker = new ( ) ;
67
68
68
69
public Channel ( ISession session , CreateChannelOptions createChannelOptions )
69
70
{
@@ -86,6 +87,8 @@ public Channel(ISession session, CreateChannelOptions createChannelOptions)
86
87
87
88
internal TimeSpan HandshakeContinuationTimeout { get ; set ; } = TimeSpan . FromSeconds ( 10 ) ;
88
89
90
+ public ShutdownEventArgs ? CloseReason => Volatile . Read ( ref _closeReason ) ;
91
+
89
92
public TimeSpan ContinuationTimeout { get ; set ; }
90
93
91
94
public event AsyncEventHandler < BasicAckEventArgs > BasicAcksAsync
@@ -548,7 +551,7 @@ protected virtual void Dispose(bool disposing)
548
551
549
552
if ( disposing )
550
553
{
551
- lock ( _isDisposingLock )
554
+ lock ( _locker )
552
555
{
553
556
if ( _isDisposing )
554
557
{
@@ -564,13 +567,20 @@ protected virtual void Dispose(bool disposing)
564
567
this . AbortAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
565
568
}
566
569
567
- ConsumerDispatcher . Dispose ( ) ;
568
- _rpcSemaphore . Dispose ( ) ;
569
- _confirmSemaphore . Dispose ( ) ;
570
- _outstandingPublisherConfirmationsRateLimiter ? . Dispose ( ) ;
570
+ MaybeWaitForServerOriginatedClose ( ) ;
571
571
}
572
572
finally
573
573
{
574
+ try
575
+ {
576
+ ConsumerDispatcher . Dispose ( ) ;
577
+ _rpcSemaphore . Dispose ( ) ;
578
+ _confirmSemaphore . Dispose ( ) ;
579
+ _outstandingPublisherConfirmationsRateLimiter ? . Dispose ( ) ;
580
+ }
581
+ catch
582
+ {
583
+ }
574
584
_disposedValue = true ;
575
585
_isDisposing = false ;
576
586
}
@@ -586,7 +596,7 @@ protected virtual async ValueTask DisposeAsyncCore(bool disposing)
586
596
587
597
if ( disposing )
588
598
{
589
- lock ( _isDisposingLock )
599
+ lock ( _locker )
590
600
{
591
601
if ( _isDisposing )
592
602
{
@@ -603,18 +613,26 @@ await this.AbortAsync()
603
613
. ConfigureAwait ( false ) ;
604
614
}
605
615
606
- ConsumerDispatcher . Dispose ( ) ;
607
- _rpcSemaphore . Dispose ( ) ;
608
- _confirmSemaphore . Dispose ( ) ;
609
-
610
616
if ( _outstandingPublisherConfirmationsRateLimiter is not null )
611
617
{
612
618
await _outstandingPublisherConfirmationsRateLimiter . DisposeAsync ( )
613
619
. ConfigureAwait ( false ) ;
614
620
}
621
+
622
+ await MaybeWaitForServerOriginatedCloseAsync ( )
623
+ . ConfigureAwait ( false ) ;
615
624
}
616
625
finally
617
626
{
627
+ try
628
+ {
629
+ ConsumerDispatcher . Dispose ( ) ;
630
+ _rpcSemaphore . Dispose ( ) ;
631
+ _confirmSemaphore . Dispose ( ) ;
632
+ }
633
+ catch
634
+ {
635
+ }
618
636
_disposedValue = true ;
619
637
_isDisposing = false ;
620
638
}
@@ -714,25 +732,39 @@ protected virtual ulong AdjustDeliveryTag(ulong deliveryTag)
714
732
715
733
protected async Task < bool > HandleChannelCloseAsync ( IncomingCommand cmd , CancellationToken cancellationToken )
716
734
{
717
- // TODO add check for Disposing / Disposed
718
- var channelClose = new ChannelClose ( cmd . MethodSpan ) ;
719
- SetCloseReason ( new ShutdownEventArgs ( ShutdownInitiator . Peer ,
720
- channelClose . _replyCode ,
721
- channelClose . _replyText ,
722
- channelClose . _classId ,
723
- channelClose . _methodId ) ) ;
724
-
725
- await Session . CloseAsync ( _closeReason , notify : false )
726
- . ConfigureAwait ( false ) ;
735
+ lock ( _locker )
736
+ {
737
+ _serverOriginatedChannelCloseTcs ??= new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
738
+ }
727
739
728
- var method = new ChannelCloseOk ( ) ;
729
- await ModelSendAsync ( in method , cancellationToken )
730
- . ConfigureAwait ( false ) ;
740
+ try
741
+ {
742
+ // TODO add check for Disposing / Disposed
743
+ var channelClose = new ChannelClose ( cmd . MethodSpan ) ;
744
+ SetCloseReason ( new ShutdownEventArgs ( ShutdownInitiator . Peer ,
745
+ channelClose . _replyCode ,
746
+ channelClose . _replyText ,
747
+ channelClose . _classId ,
748
+ channelClose . _methodId ) ) ;
731
749
732
- await Session . NotifyAsync ( cancellationToken )
733
- . ConfigureAwait ( false ) ;
750
+ await Session . CloseAsync ( _closeReason , notify : false )
751
+ . ConfigureAwait ( false ) ;
734
752
735
- return true ;
753
+ var method = new ChannelCloseOk ( ) ;
754
+ await ModelSendAsync ( in method , cancellationToken )
755
+ . ConfigureAwait ( false ) ;
756
+
757
+ await Session . NotifyAsync ( cancellationToken )
758
+ . ConfigureAwait ( false ) ;
759
+
760
+ _serverOriginatedChannelCloseTcs . TrySetResult ( true ) ;
761
+ return true ;
762
+ }
763
+ catch ( Exception ex )
764
+ {
765
+ _serverOriginatedChannelCloseTcs . TrySetException ( ex ) ;
766
+ throw ;
767
+ }
736
768
}
737
769
738
770
protected async Task < bool > HandleChannelCloseOkAsync ( IncomingCommand cmd , CancellationToken cancellationToken )
@@ -1654,5 +1686,34 @@ private Task<bool> DispatchCommandAsync(IncomingCommand cmd, CancellationToken c
1654
1686
}
1655
1687
}
1656
1688
}
1689
+
1690
+ private void MaybeWaitForServerOriginatedClose ( )
1691
+ {
1692
+ if ( _serverOriginatedChannelCloseTcs is not null )
1693
+ {
1694
+ try
1695
+ {
1696
+ _serverOriginatedChannelCloseTcs . Task . Wait ( TimeSpan . FromSeconds ( 5 ) ) ;
1697
+ }
1698
+ catch
1699
+ {
1700
+ }
1701
+ }
1702
+ }
1703
+
1704
+ private async Task MaybeWaitForServerOriginatedCloseAsync ( )
1705
+ {
1706
+ if ( _serverOriginatedChannelCloseTcs is not null )
1707
+ {
1708
+ try
1709
+ {
1710
+ await _serverOriginatedChannelCloseTcs . Task . WaitAsync ( TimeSpan . FromSeconds ( 5 ) )
1711
+ . ConfigureAwait ( false ) ;
1712
+ }
1713
+ catch
1714
+ {
1715
+ }
1716
+ }
1717
+ }
1657
1718
}
1658
1719
}
0 commit comments