On Fri, Sep 10, 2021 at 3:48 PM Ruediger Pluem <rpl...@apache.org> wrote:
>
> On 9/10/21 2:55 PM, Yann Ylavic wrote:
> >
> > Well, this rather:
> >
>
> Don't you need to create the memory for a / data->data via 
> apr_bucket_alloc(sizeof(*a), data->list)
> like we do in apr_bucket_file_make for this data structure?

Yes, I had that fixed already in my local patch (see attached).

>
> Otherwise looks good.
> And you would need to bring back
>
> old_file->filedes = -1
>
> as a partial revert of r1893204?

Yes, that was the plan.

Thanks!
Yann.
Index: buckets/apr_buckets_file.c
===================================================================
--- buckets/apr_buckets_file.c	(revision 1893196)
+++ buckets/apr_buckets_file.c	(working copy)
@@ -212,9 +212,9 @@ APR_DECLARE(apr_status_t) apr_bucket_file_set_buf_
     return APR_SUCCESS;
 }
 
-static apr_status_t file_bucket_setaside(apr_bucket *data, apr_pool_t *reqpool)
+static apr_status_t file_bucket_setaside(apr_bucket *b, apr_pool_t *reqpool)
 {
-    apr_bucket_file *a = data->data;
+    apr_bucket_file *a = b->data;
     apr_file_t *fd = NULL;
     apr_file_t *f = a->fd;
     apr_pool_t *curpool = apr_file_pool_get(f);
@@ -223,11 +223,33 @@ APR_DECLARE(apr_status_t) apr_bucket_file_set_buf_
         return APR_SUCCESS;
     }
 
-    if (!apr_pool_is_ancestor(a->readpool, reqpool)) {
-        a->readpool = reqpool;
+    /* If the file is shared/split accross multiple buckets, this bucket can't
+     * take exclusive ownership with apr_file_setaside() (thus invalidating the
+     * current/old a->fd), let's apr_file_dup() in this case instead.
+     */
+    if (a->refcount.refcount > 1) {
+        apr_bucket_file *new;
+        apr_status_t rv;
+
+        rv = apr_file_dup(&fd, f, reqpool);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+
+        new = apr_bucket_alloc(sizeof(*new), b->list);
+        memcpy(new, a, sizeof(*new));
+        new->refcount.refcount = 1;
+        new->readpool = reqpool;
+
+        a->refcount.refcount--;
+        a = b->data = new;
     }
-
-    apr_file_setaside(&fd, f, reqpool);
+    else {
+        apr_file_setaside(&fd, f, reqpool);
+        if (!apr_pool_is_ancestor(a->readpool, reqpool)) {
+            a->readpool = reqpool;
+        }
+    }
     a->fd = fd;
     return APR_SUCCESS;
 }
Index: file_io/os2/filedup.c
===================================================================
--- file_io/os2/filedup.c	(revision 1893204)
+++ file_io/os2/filedup.c	(working copy)
@@ -120,5 +120,6 @@ APR_DECLARE(apr_status_t) apr_file_setaside(apr_fi
                                   apr_file_cleanup);
     }
 
+    old_file->filedes = -1;
     return APR_SUCCESS;
 }
Index: file_io/unix/filedup.c
===================================================================
--- file_io/unix/filedup.c	(revision 1893204)
+++ file_io/unix/filedup.c	(working copy)
@@ -188,6 +188,7 @@ APR_DECLARE(apr_status_t) apr_file_setaside(apr_fi
                                      : apr_unix_child_file_cleanup);
     }
 
+    old_file->filedes = -1;
 #ifndef WAITIO_USES_POLL
     (*new_file)->pollset = NULL;
 #endif
Index: file_io/win32/filedup.c
===================================================================
--- file_io/win32/filedup.c	(revision 1893204)
+++ file_io/win32/filedup.c	(working copy)
@@ -218,6 +218,7 @@ APR_DECLARE(apr_status_t) apr_file_setaside(apr_fi
                                   file_cleanup);
     }
 
+    old_file->filehand = INVALID_HANDLE_VALUE;
 #if APR_FILES_AS_SOCKETS
     /* Create a pollset with room for one descriptor. */
     /* ### check return codes */

Reply via email to