]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Merge r660726 from trunk:
authorJim Jagielski <jim@apache.org>
Wed, 28 May 2008 12:58:29 +0000 (12:58 +0000)
committerJim Jagielski <jim@apache.org>
Wed, 28 May 2008 12:58:29 +0000 (12:58 +0000)
*  mod_proxy_http.c
   Ensure that the EOC bucket is inserted BEFORE an EOS bucket in bb as
   some resource filters like mod_deflate pass everything up to the EOS
   down the chain immediately and sent the remainder of the brigade later
   (or even never). But in this case the ap_http_header_filter does not
   get out of our way soon enough.

   http_filters.c
   Remove all data buckets that are in a brigade after an EOC bucket
   was seen, as an EOC bucket tells us that no (further) resource
   and protocol data should go out to the client. OTOH meta buckets
   are still welcome as they might trigger needed actions down in
   the chain (e.g. in network filters like SSL).
   Remark 1: It is needed to dump ALL data buckets in the brigade
             since an filter in between might have inserted data
             buckets BEFORE the EOC bucket sent by the original
             sender and we do NOT want this data to be sent.
   Remark 2: Dumping all data buckets here does not necessarily mean
             that no further data is send to the client as:
             1. Network filters like SSL can still be triggered via
                meta buckets to talk with the client e.g. for a
                clean shutdown.
             2. There could be still data that was buffered before
                down in the chain that gets flushed by a FLUSH or an
                EOS bucket.

PR: 37770

Submitted by: rpluem
Reviewed by: jim

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

STATUS
modules/http/http_filters.c
modules/proxy/mod_proxy_http.c

diff --git a/STATUS b/STATUS
index 598be0560b9d228ff701ee5890e70fcfcd98322f..0f2a88799b3eca5db9731a906d57bc1683312307 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -94,18 +94,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
- * mod_proxy: Fix a regression to 2.2.8!!! that is caused by backport
-   r657443. This regression causes blank pages to be displayed if the
-   backend connection is faulty and mod_deflate is in place.
-   More details see:
-   http://mail-archives.apache.org/mod_mbox/httpd-dev/200805.mbox/%3caafb0e350805231019tbd42c07ue7ef5fba6e46d366@mail.gmail.com%3e
-   PR 37770
-   Trunk version of patch:
-         http://svn.apache.org/viewvc?rev=660726&view=rev
-   Backport version for 2.2.x of patch:
-         Trunk version of patch works
-   +1: rpluem, fielding, jim
-
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]
index c078a7c58b33adc42f72bfea1daecbb446831913..9620fc9dfb0b10a8a026557e1d53334953592694 100644 (file)
@@ -1568,13 +1568,24 @@ AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer,
     return bufsiz;
 }
 
+/* Context struct for ap_http_outerror_filter */
+typedef struct {
+    int seen_eoc;
+} outerror_filter_ctx_t;
+
 /* Filter to handle any error buckets on output */
 apr_status_t ap_http_outerror_filter(ap_filter_t *f,
                                      apr_bucket_brigade *b)
 {
     request_rec *r = f->r;
+    outerror_filter_ctx_t *ctx = (outerror_filter_ctx_t *)(f->ctx);
     apr_bucket *e;
 
+    /* Create context if none is present */
+    if (!ctx) {
+        ctx = apr_pcalloc(r->pool, sizeof(outerror_filter_ctx_t));
+        f->ctx = ctx;
+    }
     for (e = APR_BRIGADE_FIRST(b);
          e != APR_BRIGADE_SENTINEL(b);
          e = APR_BUCKET_NEXT(e))
@@ -1588,6 +1599,40 @@ apr_status_t ap_http_outerror_filter(ap_filter_t *f,
                 /* stream aborted and we have not ended it yet */
                 r->connection->keepalive = AP_CONN_CLOSE;
             }
+            continue;
+        }
+        /* Detect EOC buckets and memorize this in the context. */
+        if (AP_BUCKET_IS_EOC(e)) {
+            ctx->seen_eoc = 1;
+        }
+    }
+    /*
+     * Remove all data buckets that are in a brigade after an EOC bucket
+     * was seen, as an EOC bucket tells us that no (further) resource
+     * and protocol data should go out to the client. OTOH meta buckets
+     * are still welcome as they might trigger needed actions down in
+     * the chain (e.g. in network filters like SSL).
+     * Remark 1: It is needed to dump ALL data buckets in the brigade
+     *           since an filter in between might have inserted data
+     *           buckets BEFORE the EOC bucket sent by the original
+     *           sender and we do NOT want this data to be sent.
+     * Remark 2: Dumping all data buckets here does not necessarily mean
+     *           that no further data is send to the client as:
+     *           1. Network filters like SSL can still be triggered via
+     *              meta buckets to talk with the client e.g. for a
+     *              clean shutdown.
+     *           2. There could be still data that was buffered before
+     *              down in the chain that gets flushed by a FLUSH or an
+     *              EOS bucket.
+     */
+    if (ctx->seen_eoc) {
+        for (e = APR_BRIGADE_FIRST(b);
+             e != APR_BRIGADE_SENTINEL(b);
+             e = APR_BUCKET_NEXT(e))
+        {
+            if (!APR_BUCKET_IS_METADATA(e)) {
+                APR_BUCKET_REMOVE(e);
+            }
         }
     }
 
index 5356f161e168fed89c9ede0eecf960ccc6156f2d..3a0f2b86577b43169fc75927d19eb493d844cad3 100644 (file)
@@ -1375,6 +1375,8 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
              * not do a retry.
              */
             if (r->proxyreq == PROXYREQ_REVERSE && c->keepalives) {
+                apr_bucket *eos;
+
                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                               "proxy: Closing connection to client because"
                               " reading from backend server %s failed. Number"
@@ -1383,10 +1385,26 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
                 ap_proxy_backend_broke(r, bb);
                 /*
                  * Add an EOC bucket to signal the ap_http_header_filter
-                 * that it should get out of our way
+                 * that it should get out of our way, BUT ensure that the
+                 * EOC bucket is inserted BEFORE an EOS bucket in bb as
+                 * some resource filters like mod_deflate pass everything
+                 * up to the EOS down the chain immediately and sent the
+                 * remainder of the brigade later (or even never). But in
+                 * this case the ap_http_header_filter does not get out of
+                 * our way soon enough.
                  */
                 e = ap_bucket_eoc_create(c->bucket_alloc);
-                APR_BRIGADE_INSERT_TAIL(bb, e);
+                eos = APR_BRIGADE_LAST(bb);
+                while ((APR_BRIGADE_SENTINEL(bb) != eos)
+                       && !APR_BUCKET_IS_EOS(eos)) {
+                    eos = APR_BUCKET_PREV(eos);
+                }
+                if (eos == APR_BRIGADE_SENTINEL(bb)) {
+                    APR_BRIGADE_INSERT_TAIL(bb, e);
+                }
+                else {
+                    APR_BUCKET_INSERT_BEFORE(eos, e);
+                }
                 ap_pass_brigade(r->output_filters, bb);
                 /* Need to return OK to avoid sending an error message */
                 return OK;