Skip to content

Commit

Permalink
* Fixed an issue where a proxy_http2 handler entered an infinit loop…
Browse files Browse the repository at this point in the history
… when encountering

   certain errors on the backend connection.
   See <https://bz.apache.org/bugzilla/show_bug.cgi?id=63170>.
  • Loading branch information
Stefan Eissing committed Feb 18, 2019
1 parent 1e4384c commit 090da49
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 27 deletions.
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
v1.12.4
--------------------------------------------------------------------------------
* Fixed an issue where a proxy_http2 handler entered an infinit loop when encountering
certain errors on the backend connection.
See <https://bz.apache.org/bugzilla/show_bug.cgi?id=63170>.

v1.12.3
--------------------------------------------------------------------------------
* fixed bug in nghttp output parsing that filters now Frames sent/received inbetween
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#

AC_PREREQ([2.69])
AC_INIT([mod_http2], [1.12.3], [[email protected]])
AC_INIT([mod_http2], [1.12.4], [[email protected]])

LT_PREREQ([2.2.6])
LT_INIT()
Expand Down
4 changes: 2 additions & 2 deletions mod_http2/h2_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
* @macro
* Version number of the http2 module as c string
*/
#define MOD_HTTP2_VERSION "1.12.3-git"
#define MOD_HTTP2_VERSION "1.12.4-git"

/**
* @macro
* Numerical representation of the version number of the http2 module
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
#define MOD_HTTP2_VERSION_NUM 0x010c03
#define MOD_HTTP2_VERSION_NUM 0x010c04


#endif /* mod_h2_h2_version_h */
55 changes: 31 additions & 24 deletions mod_http2/mod_proxy_http2.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,58 +362,65 @@ static apr_status_t proxy_engine_run(h2_proxy_ctx *ctx) {
"eng(%s): run session %s", ctx->engine_id, ctx->session->id);
ctx->session->user_data = ctx;

while (!ctx->owner->aborted) {
while (1) {
if (ctx->owner->aborted) {
status = APR_ECONNABORTED;
goto out;
}

if (APR_SUCCESS == h2_proxy_fifo_try_pull(ctx->requests, (void**)&r)) {
add_request(ctx->session, r);
}

status = h2_proxy_session_process(ctx->session);

if (status == APR_SUCCESS) {
apr_status_t s2;
/* ongoing processing, call again */
/* ongoing processing, check if we have room to handle more streams,
* maybe the remote side changed their limit */
if (ctx->session->remote_max_concurrent > 0
&& ctx->session->remote_max_concurrent != ctx->capacity) {
ctx->capacity = H2MIN((int)ctx->session->remote_max_concurrent,
h2_proxy_fifo_capacity(ctx->requests));
}
s2 = next_request(ctx, 0);
if (s2 == APR_ECONNABORTED) {
/* master connection gone */
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, s2, ctx->owner,
APLOGNO(03374) "eng(%s): pull request",
ctx->engine_id);
/* give notice that we're leaving and cancel all ongoing
* streams. */
next_request(ctx, 1);
h2_proxy_session_cancel_all(ctx->session);
h2_proxy_session_process(ctx->session);
status = ctx->r_status = APR_SUCCESS;
break;
/* try to pull more request, if our capacity allows it */
if (APR_ECONNABORTED == next_request(ctx, 0)) {
status = APR_ECONNABORTED;
goto out;
}
/* If we have no ongoing streams and nothing in our queue, we
* terminate processing and return to our caller. */
if ((h2_proxy_fifo_count(ctx->requests) == 0)
&& h2_proxy_ihash_empty(ctx->session->streams)) {
break;
goto out;
}
}
else {
/* end of processing, maybe error */
/* Encountered an error during session processing */
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, ctx->owner,
APLOGNO(03375) "eng(%s): end of session %s",
ctx->engine_id, ctx->session->id);
/*
* Any open stream of that session needs to
/* Any open stream of that session needs to
* a) be reopened on the new session iff safe to do so
* b) reported as done (failed) otherwise
*/
h2_proxy_session_cleanup(ctx->session, session_req_done);
break;
goto out;
}
}

out:
if (APR_ECONNABORTED == status) {
/* master connection gone */
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, ctx->owner,
APLOGNO(03374) "eng(%s): master connection gone", ctx->engine_id);
/* give notice that we're leaving and cancel all ongoing streams. */
next_request(ctx, 1);
h2_proxy_session_cancel_all(ctx->session);
h2_proxy_session_process(ctx->session);
status = ctx->r_status = APR_SUCCESS;
}

ctx->session->user_data = NULL;
ctx->session = NULL;

return status;
}

Expand Down Expand Up @@ -641,7 +648,7 @@ static int proxy_http2_handler(request_rec *r,
ctx->p_conn = NULL;
}

/* Any requests will still have need to fail */
/* Any requests we still have need to fail */
while (APR_SUCCESS == h2_proxy_fifo_try_pull(ctx->requests, (void**)&r)) {
request_done(ctx, r, HTTP_SERVICE_UNAVAILABLE, 1);
}
Expand Down

0 comments on commit 090da49

Please sign in to comment.