From 6a59844d480a0d3aa71ca5f3723ede4c665d0e8e Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Wed, 10 Dec 2025 14:50:42 +0100 Subject: [PATCH] stream purge Prevent double purging of a stream. Restore previous allocator for stream pools. refs PR 69899 --- mod_http2/h2_mplx.c | 23 ++++++++++++++++++----- mod_http2/h2_session.c | 18 +++++++++++++++++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/mod_http2/h2_mplx.c b/mod_http2/h2_mplx.c index 470a14ee..8053f60c 100644 --- a/mod_http2/h2_mplx.c +++ b/mod_http2/h2_mplx.c @@ -126,12 +126,24 @@ int h2_mplx_c1_stream_is_running(h2_mplx *m, h2_stream *stream) return rv; } +static int add_for_purge(h2_mplx *m, h2_stream *stream) +{ + int i; + for (i = 0; i < m->spurge->nelts; ++i) { + h2_stream *s = APR_ARRAY_IDX(m->spurge, i, h2_stream*); + if (s == stream) /* already scheduled for purging */ + return FALSE; + } + APR_ARRAY_PUSH(m->spurge, h2_stream *) = stream; + return TRUE; +} + static void c1c2_stream_joined(h2_mplx *m, h2_stream *stream) { ap_assert(!stream_is_running(stream)); h2_ihash_remove(m->shold, stream->id); - APR_ARRAY_PUSH(m->spurge, h2_stream *) = stream; + add_for_purge(m, stream); } static void m_stream_cleanup(h2_mplx *m, h2_stream *stream) @@ -164,7 +176,7 @@ static void m_stream_cleanup(h2_mplx *m, h2_stream *stream) ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c1, H2_STRM_MSG(stream, "cleanup, c2 is done, move to spurge")); /* processing has finished */ - APR_ARRAY_PUSH(m->spurge, h2_stream *) = stream; + add_for_purge(m, stream); } else { ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c1, @@ -178,9 +190,10 @@ static void m_stream_cleanup(h2_mplx *m, h2_stream *stream) } else { /* never started */ - ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c1, - H2_STRM_MSG(stream, "cleanup, never started, move to spurge")); - APR_ARRAY_PUSH(m->spurge, h2_stream *) = stream; + int added = add_for_purge(m, stream); + if (added) + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c1, + H2_STRM_MSG(stream, "cleanup, never started, move to spurge")); } } diff --git a/mod_http2/h2_session.c b/mod_http2/h2_session.c index dda6c771..2f921500 100644 --- a/mod_http2/h2_session.c +++ b/mod_http2/h2_session.c @@ -111,13 +111,29 @@ static void cleanup_unprocessed_streams(h2_session *session) h2_mplx_c1_streams_do(session->mplx, rst_unprocessed_stream, session); } +/* APR callback invoked if allocation fails. */ +static int abort_on_oom(int retcode) +{ + ap_abort_on_oom(); + return retcode; /* unreachable, hopefully. */ +} + static h2_stream *h2_session_open_stream(h2_session *session, int stream_id, int initiated_on) { h2_stream * stream; + apr_allocator_t *allocator; apr_pool_t *stream_pool; + apr_status_t rv; + + rv = apr_allocator_create(&allocator); + if (rv != APR_SUCCESS) + return NULL; - apr_pool_create(&stream_pool, session->pool); + apr_allocator_max_free_set(allocator, ap_max_mem_free); + apr_pool_create_ex(&stream_pool, session->pool, NULL, allocator); + apr_allocator_owner_set(allocator, stream_pool); + apr_pool_abort_set(abort_on_oom, stream_pool); apr_pool_tag(stream_pool, "h2_stream"); stream = h2_stream_create(stream_id, stream_pool, session,