@@ -126,6 +126,8 @@ public void Dispose()
126126 /// <returns>A task that completes when the inbound channel closes or the endpoint terminates.</returns>
127127 private async Task RunInboundPumpAsync ( )
128128 {
129+ var completeOutbound = _options . CompleteOutboundOnDispose ;
130+
129131 try
130132 {
131133 await foreach ( var message in _inbound . ReadAllAsync ( _disposeCancellation . Token ) . ConfigureAwait ( false ) )
@@ -138,15 +140,12 @@ private async Task RunInboundPumpAsync()
138140 _context . Receive ( message . Envelope , message . Options ) ;
139141 }
140142
141- Terminate (
142- new ChannelClosedException ( "Channel closed." ) ,
143- completeOutbound : true ,
144- cancelInbound : false ) ;
143+ Terminate ( new ChannelClosedException ( "Channel closed." ) , completeOutbound , cancelInbound : false ) ;
145144 }
146145 catch ( OperationCanceledException ) when ( Volatile . Read ( ref _terminalError ) is not null ) { }
147146 catch ( Exception error )
148147 {
149- Terminate ( error , completeOutbound : true , cancelInbound : false , outboundError : error ) ;
148+ Terminate ( error , completeOutbound , cancelInbound : false , outboundError : error ) ;
150149 }
151150 finally
152151 {
@@ -180,7 +179,13 @@ private void Terminate(
180179
181180 if ( cancelInbound )
182181 {
183- _disposeCancellation . Cancel ( ) ;
182+ try
183+ {
184+ // The inbound pump disposes this CTS in its finally block, so a later local Dispose
185+ // can race with that cleanup after terminal ownership has already been decided.
186+ _disposeCancellation . Cancel ( ) ;
187+ }
188+ catch ( ObjectDisposedException ) { }
184189 }
185190
186191 _context . NotifyTransportFatal ( error ) ;
0 commit comments