PATTERN Cited by 1 source
Fix at shutdown boundary¶
Fix at shutdown boundary is a defensive design pattern where a data-loss guard is placed at the exact point where irreversible action occurs (connection close, process exit, file truncation), rather than modifying the upstream control flow. This minimizes unintended side-effects on other code paths.
Rationale¶
When a bug allows premature termination of a data pipeline, there are typically two fix locations:
-
Upstream (in the processing loop): Return
Pending/block when flush is incomplete, preventing the loop from ever reaching the shutdown decision. This can cause regressions in other loop behaviors (e.g., reducing read-poll frequency, breaking keepalive connections). -
At the boundary (in the shutdown function): Before executing the irreversible action, verify that all buffered data has been drained. This is narrower in blast radius — it only fires at the moment of no return.
hyper's Implementation¶
Cloudflare initially fixed the bug in the dispatch loop (option 1), but this blocked reads during incomplete flushes and broke keepalive semantics. The upstream-accepted fix places a ready!(self.poll_flush(cx)?) guard inside poll_shutdown, ensuring all internal buffer data is flushed to the socket before shutdown(fd, SHUT_WR) is issued:
pub(crate) fn poll_shutdown(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
ready!(self.poll_flush(cx)?);
Pin::new(&mut self.io).poll_shutdown(cx)
}
The dispatch loop remains unchanged; the fix activates only at the exact moment data would otherwise be lost (Source: sources/2026-06-22-cloudflare-how-we-found-a-bug-in-the-hyper-http-library).
Applicability¶
- Any system with an internal write buffer above a kernel/transport buffer.
- Graceful shutdown paths in servers, database connections, file writers.
- Process exit handlers that must drain queues before termination.
Seen In¶
- sources/2026-06-22-cloudflare-how-we-found-a-bug-in-the-hyper-http-library — flush guard in
poll_shutdownprevents data loss in hyper