private void CloseOutboundBufferForShutdown(IChannelPipeline pipeline, ChannelOutboundBuffer buffer, Exception cause) { buffer.FailFlushed(cause, false); buffer.Close(cause, true); _ = pipeline.FireUserEventTriggered(ChannelOutputShutdownEvent.Instance); }
protected Task CloseAsync(Exception cause, bool notify) { var promise = new TaskCompletionSource(); if (!promise.SetUncancellable()) { return(promise.Task); } ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; if (outboundBuffer == null) { // Only needed if no VoidChannelPromise. if (promise != TaskCompletionSource.Void) { // This means close() was called before so we just register a listener and return return(this.channel.closeFuture.Task); } return(promise.Task); } if (this.channel.closeFuture.Task.IsCompleted) { // Closed already. Util.SafeSetSuccess(promise, Logger); return(promise.Task); } bool wasActive = this.channel.Active; this.outboundBuffer = null; // Disallow adding any messages and flushes to outboundBuffer. IEventExecutor closeExecutor = null; // todo closeExecutor(); if (closeExecutor != null) { closeExecutor.Execute(() => { try { // Execute the close. this.DoClose0(promise); } finally { // Call invokeLater so closeAndDeregister is executed input the EventLoop again! this.InvokeLater(() => { // Fail all the queued messages outboundBuffer.FailFlushed(cause, notify); outboundBuffer.Close(new ClosedChannelException()); this.FireChannelInactiveAndDeregister(wasActive); }); } }); } else { try { // Close the channel and fail the queued messages input all cases. this.DoClose0(promise); } finally { // Fail all the queued messages. outboundBuffer.FailFlushed(cause, notify); outboundBuffer.Close(new ClosedChannelException()); } if (this.inFlush0) { this.InvokeLater(() => this.FireChannelInactiveAndDeregister(wasActive)); } else { this.FireChannelInactiveAndDeregister(wasActive); } } return(promise.Task); }
Task CloseAsync(Exception cause, bool notify) { var promise = new TaskCompletionSource(); if (!promise.SetUncancellable()) { return promise.Task; } ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; if (outboundBuffer == null) { // Only needed if no VoidChannelPromise. if (promise != TaskCompletionSource.Void) { // This means close() was called before so we just register a listener and return return this.channel.closeFuture.Task; } return promise.Task; } if (this.channel.closeFuture.Task.IsCompleted) { // Closed already. Util.SafeSetSuccess(promise, Logger); return promise.Task; } bool wasActive = this.channel.Active; this.outboundBuffer = null; // Disallow adding any messages and flushes to outboundBuffer. IEventExecutor closeExecutor = null; // todo closeExecutor(); if (closeExecutor != null) { closeExecutor.Execute(() => { try { // Execute the close. this.DoClose0(promise); } finally { // Call invokeLater so closeAndDeregister is executed input the EventLoop again! this.InvokeLater(() => { // Fail all the queued messages outboundBuffer.FailFlushed(cause, notify); outboundBuffer.Close(ClosedChannelException); this.FireChannelInactiveAndDeregister(wasActive); }); } }); } else { try { // Close the channel and fail the queued messages input all cases. this.DoClose0(promise); } finally { // Fail all the queued messages. outboundBuffer.FailFlushed(cause, notify); outboundBuffer.Close(ClosedChannelException); } if (this.inFlush0) { this.InvokeLater(() => this.FireChannelInactiveAndDeregister(wasActive)); } else { this.FireChannelInactiveAndDeregister(wasActive); } } return promise.Task; }