From: Ruediger Pluem Date: Sun, 9 Dec 2007 14:54:23 +0000 (+0000) Subject: Merge r480135, r480193, r504559, r602349, r602657, r503863 from trunk: X-Git-Tag: 2.2.7~124 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1e3ed6dca09a6330769985022386dd10a3f3cb6;p=thirdparty%2Fapache%2Fhttpd.git Merge r480135, r480193, r504559, r602349, r602657, r503863 from trunk: * Apply patch for PR 41056 (19954) to fix chunk filter. Now flushes work better. * Protect against any sort of non-block read that would block. If ap_get_brigade() shows that, return EAGAIN. * Further refinement for PR41056 / PR 19954 (mostly-fixed in r480135.) We assume that a successful read but an empty brigade is NOT cause for EAGAIN. Testing may or may not confirm this assumption, in which case that test may be required as well. * If no data is available at this point of time we need to switch into the BODY_CHUNK_PART state like we do several lines later in the code in the same situation. * Case statements should go on their own line. (No functional change.) * modules/http/http_filters.c (ap_http_filter): Put case on its own line. * Add missing Changelog entry for PR41056 / PR 19954. This was fixed in r480135. PR: 41056 / 19954 Submitted by: jfclere, jim Reviewed by: rpluem, jim, jerenkrantz git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@602679 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index b20565437f3..d6c85713e96 100644 --- a/CHANGES +++ b/CHANGES @@ -1,8 +1,12 @@ -*- coding: utf-8 -*- Changes with Apache 2.2.7 + *) core: Fix broken chunk filtering that causes all non blocking reads to be + converted into blocking reads. PR 19954, 41056. + [Jean-Frederic Clere, Jim Jagielski] + *) mod_rewrite: Add the novary flag to RewriteCond. - [Ruediger Pluem] + [Ruediger Pluem] *) core: Change etag generation to produce identical results on 32-bit and 64-bit platforms. PR 40064. [Joe Orton] diff --git a/STATUS b/STATUS index 47fd23fc3a1..ad498280944 100644 --- a/STATUS +++ b/STATUS @@ -89,21 +89,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK: (NWGNUsubstitute need also be copied over from trunk, is missing in your patch) +1: jim, rpluem, fuankg - * core: Fix broken chunk filtering that causes all non blocking reads to be - converted into blocking reads - PR 19954 / 41056 - Trunk version of patch: - http://svn.apache.org/viewcvs.cgi?rev=480135&view=rev - http://svn.apache.org/viewcvs.cgi?rev=480193&view=rev - http://svn.apache.org/viewcvs.cgi?rev=504559&view=rev - http://svn.apache.org/viewcvs.cgi?rev=602349&view=rev - http://svn.apache.org/viewcvs.cgi?rev=503863&view=rev (CHANGES) - http://svn.apache.org/viewcvs.cgi?rev=602657&view=rev (style chg) - Backport version for 2.2.x of patch: - Trunk version of patch works - +1: rpluem, jim, jerenkrantz - jerenkrantz says: Feel free to apply with or withour r602657. =) - PATCHES PROPOSED TO BACKPORT FROM TRUNK: [ New proposals should be added at the end of the list ] diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c index 5e6316fdce8..e5d821cc250 100644 --- a/modules/http/http_filters.c +++ b/modules/http/http_filters.c @@ -64,7 +64,8 @@ typedef struct http_filter_ctx { enum { BODY_NONE, BODY_LENGTH, - BODY_CHUNK + BODY_CHUNK, + BODY_CHUNK_PART } state; int eos_sent; } http_ctx_t; @@ -234,7 +235,15 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc); rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE, - APR_BLOCK_READ, 0); + block, 0); + + /* for timeout */ + if (block == APR_NONBLOCK_READ && + ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) || + (APR_STATUS_IS_EAGAIN(rv)) )) { + ctx->state = BODY_CHUNK_PART; + return APR_EAGAIN; + } if (rv == APR_SUCCESS) { /* We have to check the length of the brigade we got back. @@ -297,6 +306,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ctx->eos_sent = 1; return APR_SUCCESS; case BODY_CHUNK: + case BODY_CHUNK_PART: { char line[30]; apr_bucket_brigade *bb; @@ -306,14 +316,30 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc); /* We need to read the CRLF after the chunk. */ - rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE, - APR_BLOCK_READ, 0); - apr_brigade_cleanup(bb); + if (ctx->state == BODY_CHUNK) { + rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE, + block, 0); + apr_brigade_cleanup(bb); + if (block == APR_NONBLOCK_READ && + (APR_STATUS_IS_EAGAIN(rv))) { + return APR_EAGAIN; + } + } else { + rv = APR_SUCCESS; + } if (rv == APR_SUCCESS) { /* Read the real chunk line. */ rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE, - APR_BLOCK_READ, 0); + block, 0); + /* Test timeout */ + if (block == APR_NONBLOCK_READ && + ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) || + (APR_STATUS_IS_EAGAIN(rv)) )) { + ctx->state = BODY_CHUNK_PART; + return APR_EAGAIN; + } + ctx->state = BODY_CHUNK; if (rv == APR_SUCCESS) { rv = apr_brigade_flatten(bb, line, &len); if (rv == APR_SUCCESS) {