From: Stefan Eissing Date: Thu, 10 Mar 2016 14:01:10 +0000 (+0000) Subject: Merge r1734239 from trunk: X-Git-Tag: 2.4.19~66 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cef1301b719cea31b7aae1452ccf1fd215458c9a;p=thirdparty%2Fapache%2Fhttpd.git Merge r1734239 from trunk: 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 --- diff --git a/CHANGES b/CHANGES index 2e568a91cb7..ae2ef9c041e 100644 --- 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 c76e7ba5624..5264ddaae8e 100644 --- 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 ] diff --git a/modules/filters/mod_reqtimeout.c b/modules/filters/mod_reqtimeout.c index 206e621796e..ed99c683bc9 100644 --- a/modules/filters/mod_reqtimeout.c +++ b/modules/filters/mod_reqtimeout.c @@ -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.