]> granicus.if.org Git - apache/commitdiff
mod_http2: more safe approach to async mpm keepalive connection handling
authorStefan Eissing <icing@apache.org>
Wed, 9 Mar 2016 15:37:52 +0000 (15:37 +0000)
committerStefan Eissing <icing@apache.org>
Wed, 9 Mar 2016 15:37:52 +0000 (15:37 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1734274 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/http2/h2_session.c
modules/http2/h2_session.h

diff --git a/CHANGES b/CHANGES
index 4d83effa2c7e4b5a1d19684c4b4f45d0d8183345..429651aa708879c4d2e7a1ea66586aa09ac82a79 100644 (file)
--- 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]
index 9475eb866f2d111458ef32dca362a25d5b6561ee..d99573850d5d50743b13ab9061b50ab4ddc13f89 100644 (file)
@@ -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 */
index d07ae4cc081b29b8d1c69dcec43f3f8b67a43692..fa98bf91869cc31c4c7a31e4f96a255f985998ea 100644 (file)
@@ -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 */