osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: svn commit: r1841225 - /httpd/httpd/trunk/modules/dav/main/props.c



On 10/18/2018 11:09 AM, Ruediger Pluem wrote:
> 
> 
> On 10/17/2018 07:47 PM, Joe Orton wrote:
>> On Wed, Oct 17, 2018 at 03:32:34PM +0100, Joe Orton wrote:
>>> I see constant memory use for a simple PROPFIND/depth:1 for the 
>>> attached, though I'm not sure this is sufficient to repro the problem 
>>> you saw before.

>>
>> Curiously inefficient writev use when stracing the process, though, 
>> dunno what's going on there (trunk/prefork):
>>
>> writev(46, [{iov_base="\r\n", iov_len=2}], 1) = 2
>> writev(46, [{iov_base="1f84\r\n", iov_len=6}], 1) = 6
>> writev(46, [{iov_base="<D:lockdiscovery/>\n<D:getcontent"..., iov_len=7820}], 1) = 7820
>> writev(46, [{iov_base="<D:supportedlock>\n<D:lockentry>\n"..., iov_len=248}], 1) = 248
>>
>>
> 
> The reason is ap_request_core_filter. It iterates over the brigade and hands over each bucket alone to
> ap_core_output_filter. IMHO a bug.

How about the attached patch for fixing?

Regards

Rüdiger
Index: server/request.c
===================================================================
--- server/request.c	(revision 1843972)
+++ server/request.c	(working copy)
@@ -2102,6 +2102,8 @@
             seen_eor = 1;
         }
         else {
+            int morphing_bucket = 0;
+
             /* if the core has set aside data, back off and try later */
             if (!flush_upto) {
                 if (ap_filter_should_yield(f->next)) {
@@ -2124,13 +2126,25 @@
                 if (status != APR_SUCCESS) {
                     break;
                 }
+                morphing_bucket = 1;
             }
 
             /* pass each bucket down the chain */
             APR_BUCKET_REMOVE(bucket);
             APR_BRIGADE_INSERT_TAIL(tmp_bb, bucket);
+
+            /*
+             * If we had a morphing bucket better pass things down the chain
+             * to avoid that we consume too much memory
+             */
+            if (morphing_bucket) {
+                status = ap_pass_brigade(f->next, tmp_bb);
+                apr_brigade_cleanup(tmp_bb);
+            }
         }
+    }
 
+    if ((status == APR_SUCCESS) && !APR_BRIGADE_EMPTY(tmp_bb)) {
         status = ap_pass_brigade(f->next, tmp_bb);
         apr_brigade_cleanup(tmp_bb);
     }