On Mon, Jun 24, 2019 at 09:54:21PM +0200, Ruediger Pluem wrote:
> On 06/24/2019 07:04 PM, Joe Orton wrote:
> > #11 0x00007f8110ce6448 in dav_do_prop_subreq (propdb=0x100cfc0) at 
> > props.c:331
> 
> What if you go here and do a
> 
> dump_all_pools propdb->p
> 
> and do it again when you hit the next sbrk and the next one and so on? 
> Something suspicious?

Well I did this and immediately noticed something suspicious on the 
previous line, e_uri is allocated from resource->pool (=r->pool) rather 
than propbb->p, so, yet again the precision accuracy of your insights is 
beyond belief Ruediger :) :)

This fixed a significant leak, but r->pool is still growing.  I think 
the remaining problem is use of r->pool in dav_fs_walker, i.e. is 
mod_dav_fs specific.

Unless I am missing something the apr_dir_open/apr_dir_read API design 
is always going to have memory use proportional to directory size 
because apr_dir_read() duplicates the filename into the directory's 
pool.  We need an apr_dir_pread() or whatever which takes a pool 
argument. :(

Index: modules/dav/main/mod_dav.c
===================================================================
--- modules/dav/main/mod_dav.c  (revision 1861995)
+++ modules/dav/main/mod_dav.c  (working copy)
@@ -563,6 +563,7 @@
     dav_begin_multistatus(bb, r, status, namespaces);
 
     apr_pool_create(&subpool, r->pool);
+    apr_pool_tag(subpool, "mod_dav-multistatus");
 
     for (; first != NULL; first = first->next) {
       apr_pool_clear(subpool);
@@ -2027,8 +2028,9 @@
     ** Note: we cast to lose the "const". The propdb won't try to change
     ** the resource, however, since we are opening readonly.
     */
-    err = dav_open_propdb(ctx->r, ctx->w.lockdb, wres->resource, 1,
-                          ctx->doc ? ctx->doc->namespaces : NULL, &propdb);
+    err = dav_popen_propdb(ctx->scratchpool,
+                           ctx->r, ctx->w.lockdb, wres->resource, 1,
+                           ctx->doc ? ctx->doc->namespaces : NULL, &propdb);
     if (err != NULL) {
         /* ### do something with err! */
 
Index: modules/dav/main/mod_dav.h
===================================================================
--- modules/dav/main/mod_dav.h  (revision 1861995)
+++ modules/dav/main/mod_dav.h  (working copy)
@@ -1596,6 +1596,16 @@
     apr_array_header_t *ns_xlate,
     dav_propdb **propdb);
 
+DAV_DECLARE(dav_error *) dav_popen_propdb(
+    apr_pool_t *p,
+    request_rec *r,
+    dav_lockdb *lockdb,
+    const dav_resource *resource,
+    int ro,
+    apr_array_header_t *ns_xlate,
+    dav_propdb **propdb);
+
+
 DAV_DECLARE(void) dav_close_propdb(dav_propdb *db);
 
 DAV_DECLARE(dav_get_props_result) dav_get_props(
Index: modules/dav/main/props.c
===================================================================
--- modules/dav/main/props.c    (revision 1861995)
+++ modules/dav/main/props.c    (working copy)
@@ -323,7 +323,7 @@
 {
     /* need to escape the uri that's in the resource struct because during
      * the property walker it's not encoded. */
-    const char *e_uri = ap_escape_uri(propdb->resource->pool,
+    const char *e_uri = ap_escape_uri(propdb->p,
                                       propdb->resource->uri);
 
     /* perform a "GET" on the resource's URI (note that the resource
@@ -524,22 +524,21 @@
                                         apr_array_header_t * ns_xlate,
                                         dav_propdb **p_propdb)
 {
+    return dav_popen_propdb(r->pool, r, lockdb, resource, ro, ns_xlate, 
p_propdb);
+}
+
+DAV_DECLARE(dav_error *)dav_popen_propdb(apr_pool_t *p,
+                                         request_rec *r, dav_lockdb *lockdb,
+                                         const dav_resource *resource,
+                                         int ro,
+                                         apr_array_header_t * ns_xlate,
+                                         dav_propdb **p_propdb)
+{
     dav_propdb *propdb = NULL;
-    /*
-     * Check if we have tucked away a previous propdb and reuse it.
-     * Otherwise create a new one and tuck it away
-     */
-    apr_pool_userdata_get((void **)&propdb, "propdb", r->pool);
-    if (!propdb) {
-        propdb = apr_pcalloc(r->pool, sizeof(*propdb));
-        apr_pool_userdata_setn(propdb, "propdb", NULL, r->pool);
-        apr_pool_create(&propdb->p, r->pool);
-    }
-    else {
-        /* Play safe and clear the pool of the reused probdb */
-        apr_pool_clear(propdb->p);
-    }
 
+    propdb = apr_pcalloc(p, sizeof(*propdb));
+    propdb->p = p;
+
     *p_propdb = NULL;
 
 #if DAV_DEBUG
@@ -579,8 +578,6 @@
         ap_destroy_sub_req(propdb->subreq);
         propdb->subreq = NULL;
     }
-
-    apr_pool_clear(propdb->p);
 }
 
 DAV_DECLARE(dav_get_props_result) dav_get_allprops(dav_propdb *propdb,

Reply via email to