From 0541926064c7adb62e784e146cd0e8f901b82299 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Tue, 6 Jun 2017 07:58:57 +0000 Subject: [PATCH] On the trunk: mod_http2: Fix for possible CPU busy loop introduced in v1.10.3 where a stream may keep the session in continuous check for state changes that never happen. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1797745 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 4 ++++ modules/http2/h2_mplx.c | 28 ++++++++++++++++------------ modules/http2/h2_stream.h | 1 + 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/CHANGES b/CHANGES index 9a29543268..6ef36b323d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_http2: Fix for possible CPU busy loop introduced in v1.10.3 where a stream may keep + the session in continuous check for state changes that never happen. + [Stefan Eissing] + *) Evaluate nested If/ElseIf/Else configuration blocks. [Luca Toscano, Jacob Champion] diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c index ebe0156153..b126be935f 100644 --- a/modules/http2/h2_mplx.c +++ b/modules/http2/h2_mplx.c @@ -1057,19 +1057,23 @@ apr_status_t h2_mplx_idle(h2_mplx *m) "h2_mplx(%ld): idle, no tasks ongoing, %d streams", m->id, (int)h2_ihash_count(m->streams)); h2_ihash_shift(m->streams, (void**)&stream, 1); - if (stream && stream->output) { - /* FIXME: this looks like a race between the session thinking - * it is idle and the EOF on a stream not being sent. - * Signal to caller to leave IDLE state. - */ - ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c, - H2_STRM_MSG(stream, "output closed=%d, mplx idle" - ", out has %ld bytes buffered"), - h2_beam_is_closed(stream->output), - (long)h2_beam_get_buffered(stream->output)); + if (stream) { h2_ihash_add(m->streams, stream); - check_data_for(m, stream, 0); - status = APR_EAGAIN; + if (stream->output && !stream->out_checked) { + /* FIXME: this looks like a race between the session thinking + * it is idle and the EOF on a stream not being sent. + * Signal to caller to leave IDLE state. + */ + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c, + H2_STRM_MSG(stream, "output closed=%d, mplx idle" + ", out has %ld bytes buffered"), + h2_beam_is_closed(stream->output), + (long)h2_beam_get_buffered(stream->output)); + h2_ihash_add(m->streams, stream); + check_data_for(m, stream, 0); + stream->out_checked = 1; + status = APR_EAGAIN; + } } } } diff --git a/modules/http2/h2_stream.h b/modules/http2/h2_stream.h index f328714951..c3b4b844fd 100644 --- a/modules/http2/h2_stream.h +++ b/modules/http2/h2_stream.h @@ -89,6 +89,7 @@ struct h2_stream { unsigned int scheduled : 1; /* stream has been scheduled */ unsigned int has_response : 1; /* response headers are known */ unsigned int input_eof : 1; /* no more request data coming */ + unsigned int out_checked : 1; /* output eof was double checked */ unsigned int push_policy; /* which push policy to use for this request */ struct h2_task *task; /* assigned task to fullfill request */ -- 2.50.1