]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Merge r1734239 from trunk:
authorStefan Eissing <icing@apache.org>
Thu, 10 Mar 2016 14:01:10 +0000 (14:01 +0000)
committerStefan Eissing <icing@apache.org>
Thu, 10 Mar 2016 14:01:10 +0000 (14:01 +0000)
mod_reqtimeout: Prevent long response times from triggering a timeout once
the request has been fully read.  PR 59045.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1734416 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
modules/filters/mod_reqtimeout.c

diff --git a/CHANGES b/CHANGES
index 2e568a91cb70d8af134696903c8d991328fdf045..ae2ef9c041e8521e99476aa76e502048d4012322 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,9 @@
 
 Changes with Apache 2.4.19
 
+  *) mod_reqtimeout: Prevent long response times from triggering a timeout once
+     the request has been fully read.  PR 59045.  [Yann Ylavic]
+
   *) 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. [Stefan Eissing]
diff --git a/STATUS b/STATUS
index c76e7ba56241a842051fd465dbdd084f5b2b61b2..5264ddaae8e38503e00941d0a8cc6a6180403d52 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -112,12 +112,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-  *) mod_reqtimeout: Prevent long response times from triggering a timeout once
-     the request has been fully read.  PR 59045.
-     trunk patch: http://svn.apache.org/r1734239
-     2.4.x patch: trunk works (module CHANGES)
-     +1: ylavic, rpluem, icing
-
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]
index 206e621796eadd1ab9a7b2b33d565d0a5f90c00a..ed99c683bc9ca35778545f9d2cf1f045e3807ff7 100644 (file)
@@ -177,16 +177,6 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f,
     apr_interval_time_t saved_sock_timeout = UNSET;
     reqtimeout_con_cfg *ccfg = f->ctx;
 
-    if (block == APR_NONBLOCK_READ && mode == AP_MODE_SPECULATIVE) { 
-        /*  The source of these above us in the core is check_pipeline(), which
-         *  is between requests but before this filter knows to reset timeouts 
-         *  during pre_read_request().  If they appear elsewhere, just don't 
-         *  check or extend the time since they won't block and we'll see the
-         *  bytes again later
-         */
-        return ap_get_brigade(f->next, bb, mode, block, readbytes);
-    }
-
     if (ccfg->in_keep_alive) {
         /* For this read[_request line()], wait for the first byte using the
          * normal keep-alive timeout (hence don't take this expected idle time
@@ -211,7 +201,7 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f,
         }
     }
     else if (ccfg->timeout_at == 0) {
-        /* no timeout set */
+        /* no timeout set, or in between requests */
         return ap_get_brigade(f->next, bb, mode, block, readbytes);
     }
 
@@ -315,8 +305,7 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f,
             APR_BRIGADE_PREPEND(bb, ccfg->tmpbb);
 
     }
-    else {
-        /* mode != AP_MODE_GETLINE */
+    else { /* mode != AP_MODE_GETLINE */
         rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
         /* Don't extend the timeout in speculative mode, wait for
          * the real (relevant) bytes to be asked later, within the
@@ -352,6 +341,15 @@ out:
     return rv;
 }
 
+static apr_status_t reqtimeout_eor(ap_filter_t *f, apr_bucket_brigade *bb)
+{
+    if (!APR_BRIGADE_EMPTY(bb) && AP_BUCKET_IS_EOR(APR_BRIGADE_LAST(bb))) {
+        reqtimeout_con_cfg *ccfg = f->ctx;
+        ccfg->timeout_at = 0;
+    }
+    return ap_pass_brigade(f->next, bb);
+}
+
 static int reqtimeout_init(conn_rec *c)
 {
     reqtimeout_con_cfg *ccfg;
@@ -369,6 +367,7 @@ static int reqtimeout_init(conn_rec *c)
     if (ccfg == NULL) {
         ccfg = apr_pcalloc(c->pool, sizeof(reqtimeout_con_cfg));
         ap_set_module_config(c->conn_config, &reqtimeout_module, ccfg);
+        ap_add_output_filter(reqtimeout_filter_name, ccfg, NULL, c);
         ap_add_input_filter(reqtimeout_filter_name, ccfg, NULL, c);
     }
 
@@ -606,6 +605,14 @@ static void reqtimeout_hooks(apr_pool_t *pool)
     ap_register_input_filter(reqtimeout_filter_name, reqtimeout_filter, NULL,
                              AP_FTYPE_CONNECTION + 8);
 
+    /*
+     * We need to pause timeout detection in between requests, for
+     * speculative and non-blocking reads, so between each outgoing EOR
+     * and the next pre_read_request call.
+     */
+    ap_register_output_filter(reqtimeout_filter_name, reqtimeout_eor, NULL,
+                              AP_FTYPE_CONNECTION);
+
     /*
      * mod_reqtimeout needs to be called before ap_process_http_request (which
      * is run at APR_HOOK_REALLY_LAST) but after all other protocol modules.