Skip to main content

close_after_draining

Function close_after_draining 

Source
async fn close_after_draining(drain: Duration, ctx: &ForwardCtx)
Expand description

Give this session’s egress queues drain to empty, then end it.

The close code and reason are already in the session’s closer — a requested close records them before it sends the request, so that a session torn down by its peer half a millisecond later still closes with what was asked for. This function’s only job is the window, and what happens at the end of it.

§Draining means the queues emptied, not that the timer expired

The wait ends the moment EgressGauge reads zero, which on a session with nothing deferred is the first poll. Waiting out the full window unconditionally would put a fixed cost on every close, and the cost is the wrong one: it is paid by the sessions that had nothing to flush.

§And what is left is abandoned rather than flushed

The queues are put into discarding mode before the cancellation, so the cancel arm of every pipe writes nothing and reports its whole remainder as Impairment { QueuedBytesAtTeardown }. That is the opposite of what an unrequested teardown does, and the difference is the deadline: an ordinary teardown’s best-effort flush is the last chance those bytes have, while a close that was given a window and spent it has already decided. Flushing past that point would hand the bytes to a connection about to send CONNECTION_CLOSE, which discards its buffer — so they would be neither confirmably delivered nor confirmably lost, and the one arithmetic a caller can check would stop closing.

The cancellation is unconditional and comes last, so a session whose drain completed and one whose drain expired end the same way and with the same close arguments.