Meanwhile I identified 3 others positions in the proxy code path which can 
cause this kind of trouble.
Please find the updated patches attached. Using APR_BRIGADE_CONCAT in a loop 
with ap_get_brigade
on the same brigade seems to be troublesome :-).

Regards

Rüdiger

On 10/19/2005 11:10 AM, Ruediger Pluem wrote:
> Attached my (currently) final versions of the patches to fix PR37145 on 2.0.x 
> (37145_2.0.x.diff)
> and on trunk (37145.diff). Comments / thoughts / votes are highly appreciated 
> as I want to
> commit to trunk and propose it for backport in 2.0.x.
> 
> Regards
> 
> Rüdiger
> 
> On 10/19/2005 02:46 AM, Ruediger Pluem wrote:
> 
>>Attached a new version of the patch that uses ap_save_brigade.
>>Again for 2.0.x.
>>
>>Regards
>>
>>Rüdiger
>>
>>
>>On 10/19/2005 02:18 AM, Ruediger Pluem wrote:
>>
>>
>>>The following patch should fix PR37145. I would like to hear some comments / 
>>>thoughts
>>
>>>from brigade / buckets and proxy gurus on this.
>>
>>>Although this problem has been reported against 2.0.55, I cross checked
>>>and this problem is also in the trunk.
>>>
>>>Regards
>>>
>>>Rüdiger
>>>
Index: modules/proxy/mod_proxy_http.c
===================================================================
--- modules/proxy/mod_proxy_http.c      (Revision 326481)
+++ modules/proxy/mod_proxy_http.c      (Arbeitskopie)
@@ -247,7 +247,21 @@
              * take care of that now
              */
             bb = header_brigade;
-            APR_BRIGADE_CONCAT(bb, input_brigade);
+
+            /*
+             * Save input_brigade in bb brigade. (At least) in the SSL case
+             * input_brigade contains transient buckets whose data would get
+             * overwritten during the next call of ap_get_brigade in the loop.
+             * ap_save_brigade ensures these buckets to be set aside.
+             * Calling ap_save_brigade with NULL as filter is OK, because
+             * bb brigade already has been created and does not need to get
+             * created by ap_save_brigade.
+             */
+            status = ap_save_brigade(NULL, &bb, &input_brigade, p);
+            if (status != APR_SUCCESS) {
+                return status;
+            }
+
             header_brigade = NULL;
         }
         else {
@@ -354,7 +368,21 @@
              * take care of that now
              */
             bb = header_brigade;
-            APR_BRIGADE_CONCAT(bb, input_brigade);
+
+            /*
+             * Save input_brigade in bb brigade. (At least) in the SSL case
+             * input_brigade contains transient buckets whose data would get
+             * overwritten during the next call of ap_get_brigade in the loop.
+             * ap_save_brigade ensures these buckets to be set aside.
+             * Calling ap_save_brigade with NULL as filter is OK, because
+             * bb brigade already has been created and does not need to get
+             * created by ap_save_brigade.
+             */
+            status = ap_save_brigade(NULL, &bb, &input_brigade, p);
+            if (status != APR_SUCCESS) {
+                return status;
+            }
+
             header_brigade = NULL;
         }
         else {
@@ -476,7 +504,21 @@
             apr_brigade_cleanup(input_brigade);
         }
         else {
-            APR_BRIGADE_CONCAT(body_brigade, input_brigade);
+
+            /*
+             * Save input_brigade in body_brigade. (At least) in the SSL case
+             * input_brigade contains transient buckets whose data would get
+             * overwritten during the next call of ap_get_brigade in the loop.
+             * ap_save_brigade ensures these buckets to be set aside.
+             * Calling ap_save_brigade with NULL as filter is OK, because
+             * body_brigade already has been created and does not need to get
+             * created by ap_save_brigade.
+             */
+            status = ap_save_brigade(NULL, &body_brigade, &input_brigade, p);
+            if (status != APR_SUCCESS) {
+                return status;
+            }
+
         }
         
         bytes_spooled += bytes;
@@ -832,9 +874,27 @@
         }
 
         apr_brigade_length(temp_brigade, 1, &bytes);
-        APR_BRIGADE_CONCAT(input_brigade, temp_brigade);
         bytes_read += bytes;
 
+        /*
+         * Save temp_brigade in input_brigade. (At least) in the SSL case
+         * temp_brigade contains transient buckets whose data would get
+         * overwritten during the next call of ap_get_brigade in the loop.
+         * ap_save_brigade ensures these buckets to be set aside.
+         * Calling ap_save_brigade with NULL as filter is OK, because
+         * input_brigade already has been created and does not need to get
+         * created by ap_save_brigade.
+         */
+        status = ap_save_brigade(NULL, &input_brigade, &temp_brigade, p);
+        if (status != APR_SUCCESS) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
+                         "proxy: processing prefetched request body failed"
+                         " to %pI (%s) from %s (%s)",
+                         p_conn->addr, p_conn->hostname ? p_conn->hostname: "",
+                         c->remote_ip, c->remote_host ? c->remote_host: "");
+            return status;
+        }
+
     /* Ensure we don't hit a wall where we have a buffer too small
      * for ap_get_brigade's filters to fetch us another bucket,
      * surrender once we hit 80 bytes less than MAX_MEM_SPOOL
Index: modules/proxy/proxy_http.c
===================================================================
--- modules/proxy/proxy_http.c  (Revision 326480)
+++ modules/proxy/proxy_http.c  (Arbeitskopie)
@@ -504,7 +504,21 @@
              * take care of that now
              */
             bb = header_brigade;
-            APR_BRIGADE_CONCAT(bb, input_brigade);
+
+            /*
+             * Save input_brigade in bb brigade. (At least) in the SSL case
+             * input_brigade contains transient buckets whose data would get
+             * overwritten during the next call of ap_get_brigade in the loop.
+             * ap_save_brigade ensures these buckets to be set aside.
+             * Calling ap_save_brigade with NULL as filter is OK, because
+             * bb brigade already has been created and does not need to get
+             * created by ap_save_brigade.
+             */
+            status = ap_save_brigade(NULL, &bb, &input_brigade, p);
+            if (status != APR_SUCCESS) {
+                return status;
+            }
+
             header_brigade = NULL;
         }
         else {
@@ -611,7 +625,21 @@
              * take care of that now
              */
             bb = header_brigade;
-            APR_BRIGADE_CONCAT(bb, input_brigade);
+
+            /*
+             * Save input_brigade in bb brigade. (At least) in the SSL case
+             * input_brigade contains transient buckets whose data would get
+             * overwritten during the next call of ap_get_brigade in the loop.
+             * ap_save_brigade ensures these buckets to be set aside.
+             * Calling ap_save_brigade with NULL as filter is OK, because
+             * bb brigade already has been created and does not need to get
+             * created by ap_save_brigade.
+             */
+            status = ap_save_brigade(NULL, &bb, &input_brigade, p);
+            if (status != APR_SUCCESS) {
+                return status;
+            }
+
             header_brigade = NULL;
         }
         else {
@@ -735,7 +763,21 @@
             apr_brigade_cleanup(input_brigade);
         }
         else {
-            APR_BRIGADE_CONCAT(body_brigade, input_brigade);
+
+            /*
+             * Save input_brigade in body_brigade. (At least) in the SSL case
+             * input_brigade contains transient buckets whose data would get
+             * overwritten during the next call of ap_get_brigade in the loop.
+             * ap_save_brigade ensures these buckets to be set aside.
+             * Calling ap_save_brigade with NULL as filter is OK, because
+             * body_brigade already has been created and does not need to get
+             * created by ap_save_brigade.
+             */
+            status = ap_save_brigade(NULL, &body_brigade, &input_brigade, p);
+            if (status != APR_SUCCESS) {
+                return status;
+            }
+
         }
         
         bytes_spooled += bytes;
@@ -1081,9 +1123,27 @@
         }
 
         apr_brigade_length(temp_brigade, 1, &bytes);
-        APR_BRIGADE_CONCAT(input_brigade, temp_brigade);
         bytes_read += bytes;
 
+        /*
+         * Save temp_brigade in input_brigade. (At least) in the SSL case
+         * temp_brigade contains transient buckets whose data would get
+         * overwritten during the next call of ap_get_brigade in the loop.
+         * ap_save_brigade ensures these buckets to be set aside.
+         * Calling ap_save_brigade with NULL as filter is OK, because
+         * input_brigade already has been created and does not need to get
+         * created by ap_save_brigade.
+         */
+        status = ap_save_brigade(NULL, &input_brigade, &temp_brigade, p);
+        if (status != APR_SUCCESS) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
+                         "proxy: processing prefetched request body failed"
+                         " to %s from %s (%s)",
+                         p_conn->name ? p_conn->name: "",
+                         c->remote_ip, c->remote_host ? c->remote_host: "");
+            return status;
+        }
+
     /* Ensure we don't hit a wall where we have a buffer too small
      * for ap_get_brigade's filters to fetch us another bucket,
      * surrender once we hit 80 bytes less than MAX_MEM_SPOOL

Reply via email to