diff options
author | Yann Ylavic <ylavic@apache.org> | 2021-09-19 16:53:44 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2021-09-19 16:53:44 +0000 |
commit | d64a6c690f98bfb053b5540b76fbed77e085a921 (patch) | |
tree | 9c8a1ca9bd53cf4dcc2669cf2c2bd83d5f4bd77f | |
parent | 6b38a462b14878a54734fa090e6f417a6c0c09a8 (diff) | |
download | apr-d64a6c690f98bfb053b5540b76fbed77e085a921.tar.gz |
Follow up to r1893204: restore apr_file_setaside() semantics, fix file_bucket_setaside().
apr_file_setasidea() needs to invalidate the old file descriptor per semantics:
* @remark After calling this function, old_file may not be used
So to avoid the setaside issue with splitted file buckets, file_bucket_setaside()
will now apr_file_dup() instead of apr_file_setaside() when the bucket is shared
(i.e. refcount > 1).
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1893445 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | buckets/apr_buckets_file.c | 34 | ||||
-rw-r--r-- | file_io/os2/filedup.c | 1 | ||||
-rw-r--r-- | file_io/unix/filedup.c | 1 | ||||
-rw-r--r-- | file_io/win32/filedup.c | 1 |
4 files changed, 31 insertions, 6 deletions
diff --git a/buckets/apr_buckets_file.c b/buckets/apr_buckets_file.c index 82bb2d172..be0bda0d8 100644 --- a/buckets/apr_buckets_file.c +++ b/buckets/apr_buckets_file.c @@ -212,9 +212,9 @@ APR_DECLARE(apr_status_t) apr_bucket_file_set_buf_size(apr_bucket *e, 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 @@ static apr_status_t file_bucket_setaside(apr_bucket *data, apr_pool_t *reqpool) 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 + * f->filedes), 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; + } - apr_file_setaside(&fd, f, reqpool); + 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; + } + else { + apr_file_setaside(&fd, f, reqpool); + if (!apr_pool_is_ancestor(a->readpool, reqpool)) { + a->readpool = reqpool; + } + } a->fd = fd; return APR_SUCCESS; } diff --git a/file_io/os2/filedup.c b/file_io/os2/filedup.c index 15040c7c6..57e5d5771 100644 --- a/file_io/os2/filedup.c +++ b/file_io/os2/filedup.c @@ -120,5 +120,6 @@ APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file, apr_file_cleanup); } + old_file->filedes = -1; return APR_SUCCESS; } diff --git a/file_io/unix/filedup.c b/file_io/unix/filedup.c index 446642b3f..a8e14acfb 100644 --- a/file_io/unix/filedup.c +++ b/file_io/unix/filedup.c @@ -188,6 +188,7 @@ APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file, : apr_unix_child_file_cleanup); } + old_file->filedes = -1; #ifndef WAITIO_USES_POLL (*new_file)->pollset = NULL; #endif diff --git a/file_io/win32/filedup.c b/file_io/win32/filedup.c index 9b4730199..662786421 100644 --- a/file_io/win32/filedup.c +++ b/file_io/win32/filedup.c @@ -218,6 +218,7 @@ APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file, file_cleanup); } + old_file->filehand = INVALID_HANDLE_VALUE; #if APR_FILES_AS_SOCKETS /* Create a pollset with room for one descriptor. */ /* ### check return codes */ |