From: Stefan Eissing Date: Wed, 9 Mar 2016 15:37:52 +0000 (+0000) Subject: mod_http2: more safe approach to async mpm keepalive connection handling X-Git-Tag: 2.5.0-alpha~1934 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e79d2bb45e46d43fd0953cf691d0d8a72adf2615;p=apache mod_http2: more safe approach to async mpm keepalive connection handling git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1734274 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 4d83effa2c..429651aa70 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_http2: give control to async mpm for keepalive timeouts only when + no streams are open and even if only after 1 sec delay. Under load, event + mpm discards connections otherwise too quickly. + *) mod_proxy_http2: rescheduling of requests that have not been processed by the backend when receiving a GOAWAY frame before done. [Stefan Eissign] diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c index 9475eb866f..d99573850d 100644 --- a/modules/http2/h2_session.c +++ b/modules/http2/h2_session.c @@ -1801,12 +1801,14 @@ static void h2_session_ev_no_io(h2_session *session, int arg, const char *msg) transit(session, "no io", H2_SESSION_ST_DONE); } else { + apr_time_t now = apr_time_now(); /* When we have no streams, no task event are possible, * switch to blocking reads */ transit(session, "no io", H2_SESSION_ST_IDLE); session->idle_until = (session->requests_received? session->s->keep_alive_timeout : - session->s->timeout) + apr_time_now(); + session->s->timeout) + now; + session->keep_sync_until = now + apr_time_from_sec(1); } } else if (!has_unsubmitted_streams(session) @@ -1817,6 +1819,7 @@ static void h2_session_ev_no_io(h2_session *session, int arg, const char *msg) * window updates. */ transit(session, "no io", H2_SESSION_ST_IDLE); session->idle_until = apr_time_now() + session->s->timeout; + session->keep_sync_until = session->idle_until; } else { /* Unable to do blocking reads, as we wait on events from @@ -2014,7 +2017,8 @@ apr_status_t h2_session_process(h2_session *session, int async) : SERVER_BUSY_READ), "idle"); /* make certain, the client receives everything before we idle */ h2_conn_io_flush(&session->io); - if (async && no_streams && !session->r && session->requests_received) { + if (!session->keep_sync_until + && async && no_streams && !session->r && session->requests_received) { ap_log_cerror( APLOG_MARK, APLOG_TRACE1, status, c, "h2_session(%ld): async idle, nonblock read", session->id); /* We do not return to the async mpm immediately, since under @@ -2067,7 +2071,13 @@ apr_status_t h2_session_process(h2_session *session, int async) /* nothing to read */ } else if (APR_STATUS_IS_TIMEUP(status)) { - if (apr_time_now() > session->idle_until) { + apr_time_t now = apr_time_now(); + if (now > session->keep_sync_until) { + /* if we are on an async mpm, now is the time that + * we may dare to pass control to it. */ + session->keep_sync_until = 0; + } + if (now > session->idle_until) { dispatch_event(session, H2_SESSION_EV_CONN_TIMEOUT, 0, "timeout"); } /* continue reading handling */ diff --git a/modules/http2/h2_session.h b/modules/http2/h2_session.h index d07ae4cc08..fa98bf9186 100644 --- a/modules/http2/h2_session.h +++ b/modules/http2/h2_session.h @@ -108,6 +108,7 @@ typedef struct h2_session { apr_time_t start_wait; /* Time we started waiting for sth. to happen */ apr_time_t idle_until; /* Time we shut down due to sheer boredom */ + apr_time_t keep_sync_until; /* Time we sync wait until passing to async mpm */ apr_pool_t *pool; /* pool to use in session handling */ apr_bucket_brigade *bbtmp; /* brigade for keeping temporary data */