On Fri, Sep 10, 2021 at 1:32 PM Yann Ylavic <ylavic....@gmail.com> wrote:
>
> On Fri, Sep 10, 2021 at 11:12 AM Ruediger Pluem <rpl...@apache.org> wrote:
> >
> > On 9/10/21 11:04 AM, Ruediger Pluem wrote:
> > >
> > > On 9/10/21 8:55 AM, Joe Orton wrote:
> > >> On Fri, Sep 10, 2021 at 12:51:53AM -0000, yla...@apache.org wrote:
> > >>>
> > >>> apr_file_setaside: don't blindly kill the old cleanup and file 
> > >>> descriptor.
> > >>>
> > >>> There is no cleanup with APR_FOPEN_NOCLEANUP, so 
> > >>> apr_pool_cleanup_kill() can
> > >>> go in the !(old_file->flags & APR_FOPEN_NOCLEANUP) block.
> > >>>
> > >>> The file descriptor can't be invalidated either, the file may be split 
> > >>> in
> > >>> multiple buckets and setting aside one shouldn't invalidate the others.
> > >>
> > >> Interesting.  So is the API claim that:
> > >>
> > >>  * @remark After calling this function, old_file may not be used
> > >>
> > >> not really correct, or needs to be weakened?
> > >
> > > I think it is correct, for the reason you state below and the reason I 
> > > mentioned,
> > > but I guess we probably need to review in httpd land if we still use the 
> > > old_file
> > > afterwards e.g. when buckets have been split.
>
> The fix still belongs in APR though, being able to split and setaside
> file buckets is broken for now.
>
> >
> > I think the old code with setting the file descriptor of old_file to -1, 
> > should reveal
> > in a clear way if we still use the old file afterwards. Keeping the file 
> > descriptor may
> > lead to subtle failures some time later that are hard to debug.
>
> OK, the semantics of apr_file_setaside() are to take ownership
> (invalidate the old fd) and we probably can't change that.
>
> So we need to fix file_bucket_setaside() somehow, like this?

Well, this rather:

Index: buckets/apr_buckets_file.c
===================================================================
--- buckets/apr_buckets_file.c    (revision 1893196)
+++ buckets/apr_buckets_file.c    (working copy)
@@ -18,6 +18,7 @@
 #include "apr_general.h"
 #include "apr_file_io.h"
 #include "apr_buckets.h"
+#include "apr_strings.h" /* for apr_pmemdup() */

 #if APR_HAS_MMAP
 #include "apr_mmap.h"
@@ -218,16 +219,34 @@ static apr_status_t file_bucket_setaside(apr_bucke
     apr_file_t *fd = NULL;
     apr_file_t *f = a->fd;
     apr_pool_t *curpool = apr_file_pool_get(f);
+    apr_status_t rv;

     if (apr_pool_is_ancestor(curpool, reqpool)) {
         return APR_SUCCESS;
     }

+    /* If the file is shared/split this bucket can't take exclusive ownership
+     * with apr_file_setaside() (which invalidates the current/old a->fd,) so
+     * we need to dup in this case.
+     */
+    if (a->refcount.refcount > 1) {
+        rv = apr_file_dup(&fd, f, reqpool);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+        a->refcount.refcount--;
+        a = data->data = apr_pmemdup(reqpool, a, sizeof(*a));
+        a->refcount.refcount = 1;
+    }
+    else {
+        rv = apr_file_setaside(&fd, f, reqpool);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+    }
     if (!apr_pool_is_ancestor(a->readpool, reqpool)) {
         a->readpool = reqpool;
     }
-
-    apr_file_setaside(&fd, f, reqpool);
     a->fd = fd;
     return APR_SUCCESS;
 }
--

Reply via email to