Skip to content

Fix connection leak on client abort - #12529

Merged
masaori335 merged 1 commit into
apache:masterfrom
masaori335:background_fill_and_cache_read
Sep 25, 2025
Merged

Fix connection leak on client abort#12529
masaori335 merged 1 commit into
apache:masterfrom
masaori335:background_fill_and_cache_read

Conversation

@masaori335

@masaori335 masaori335 commented Sep 24, 2025

Copy link
Copy Markdown
Contributor

We faced two issues with #12502 deployment.

A). client side connection is not closed when the client aborts during cache read
B). HTTP/2 connection is closed if a stream is reset even if other streams are alive

Approach for A). restore code prior to #12502 and narrow down condition to keep HttpSM running
Approach for B). call ProxyTransaction::do_io_shutdown() instead of NetVConnection::do_io_shutdown()

Notes from @bryancall:
@bneradt observed client connection leaks in production without this change. The connection count was increasing and the servers were taking out of rotation because we have checks on the connection counts.

@masaori335 masaori335 added this to the 10.2.0 milestone Sep 24, 2025
@masaori335
masaori335 requested a review from bneradt September 24, 2025 07:52
@masaori335 masaori335 self-assigned this Sep 24, 2025
Comment thread src/proxy/http/HttpSM.cc
netvc->do_io_shutdown(IO_SHUTDOWN_READWRITE);
}
} else if (t_state.txn_conf->cache_http &&
(server_entry != nullptr && server_entry->vc_read_handler == &HttpSM::state_read_server_response_header)) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we compare with 244d82a (the parent commit of #12502), adding this else if block is the main change.

@masaori335
masaori335 merged commit 1754d38 into apache:master Sep 25, 2025
15 checks passed
@github-project-automation github-project-automation Bot moved this to For v10.1.1 in ATS v10.1.x Sep 25, 2025
@cmcfarlen cmcfarlen moved this from For v10.1.1 to Picked v10.1.1 in ATS v10.1.x Oct 7, 2025
@cmcfarlen cmcfarlen modified the milestones: 10.2.0, 10.1.1 Oct 7, 2025
@cmcfarlen

Copy link
Copy Markdown
Contributor

Cherry-picked to 10.1.x branch

cmcfarlen pushed a commit that referenced this pull request Oct 7, 2025
bneradt added a commit that referenced this pull request Aug 10, 2026
…13523)

HttpSM::state_watch_for_client_abort reached past the transaction to
_ua.get_txn()->get_netvc() to half close the client read side on an early
EOS. For HTTP/2 and HTTP/3 that NetVConnection is shared by every stream
on the connection, so a single aborted stream stopped the session from
reading frames for all of the others. Route the shutdown through the
transaction instead: Http2Stream and HQTransaction already implement
do_io_shutdown() as a deliberate no-op for exactly this reason, and
HTTP/1.x is unaffected because ProxyTransaction forwards to the session's
NetVConnection.

This is the remaining half of #12529. That change was written to address
two regressions from #12502, the second being "HTTP/2 connection is
closed if a stream is reset even if other streams are alive", with the
stated approach of calling ProxyTransaction::do_io_shutdown() instead of
NetVConnection::do_io_shutdown(). It converted the two branches it added
but left the pre-existing IO_SHUTDOWN_READ branch calling the
NetVConnection directly, so the connection-wide shutdown survived for the
case where the tunnel still has a consumer besides the client. A response
transform reaches that case readily: the transform stage runs the whole
body before anything is written back, so the stream has no write of its
own and a client reset arrives as an EOS on the stream's read VIO.

Clearing the session's read VIO buffer is not inert, because
Http2CommonSession still holds that VIO and re-enables it every 128
frames through HTTP2_SESSION_EVENT_REENABLE. A release build then takes
the ntodo() <= 0 path in net_read_io and the connection stalls silently,
failing every in-flight stream; a debug build aborts on
SSLNetVConnection's `ink_assert(buf.writer())`, the assertion reported
in #9448.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
cmcfarlen pushed a commit that referenced this pull request Aug 10, 2026
…13523)

HttpSM::state_watch_for_client_abort reached past the transaction to
_ua.get_txn()->get_netvc() to half close the client read side on an early
EOS. For HTTP/2 and HTTP/3 that NetVConnection is shared by every stream
on the connection, so a single aborted stream stopped the session from
reading frames for all of the others. Route the shutdown through the
transaction instead: Http2Stream and HQTransaction already implement
do_io_shutdown() as a deliberate no-op for exactly this reason, and
HTTP/1.x is unaffected because ProxyTransaction forwards to the session's
NetVConnection.

This is the remaining half of #12529. That change was written to address
two regressions from #12502, the second being "HTTP/2 connection is
closed if a stream is reset even if other streams are alive", with the
stated approach of calling ProxyTransaction::do_io_shutdown() instead of
NetVConnection::do_io_shutdown(). It converted the two branches it added
but left the pre-existing IO_SHUTDOWN_READ branch calling the
NetVConnection directly, so the connection-wide shutdown survived for the
case where the tunnel still has a consumer besides the client. A response
transform reaches that case readily: the transform stage runs the whole
body before anything is written back, so the stream has no write of its
own and a client reset arrives as an EOS on the stream's read VIO.

Clearing the session's read VIO buffer is not inert, because
Http2CommonSession still holds that VIO and re-enables it every 128
frames through HTTP2_SESSION_EVENT_REENABLE. A release build then takes
the ntodo() <= 0 path in net_read_io and the connection stalls silently,
failing every in-flight stream; a debug build aborts on
SSLNetVConnection's `ink_assert(buf.writer())`, the assertion reported
in #9448.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 31eb68f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Picked v10.1.1

Development

Successfully merging this pull request may close these issues.

3 participants