diff options
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | file_io/unix/filedup.c | 4 | ||||
-rw-r--r-- | file_io/unix/open.c | 4 | ||||
-rw-r--r-- | file_io/unix/readwrite.c | 61 | ||||
-rw-r--r-- | file_io/unix/seek.c | 5 | ||||
-rw-r--r-- | include/arch/unix/apr_arch_file_io.h | 14 |
6 files changed, 53 insertions, 38 deletions
@@ -1,5 +1,8 @@ Changes with APR 0.9.14 + *) Improve thread safety of assorted file_io functions. + PR 42400. [Davi Arnaut <davi haxent.com.br>] + *) Fix file pointer position calculation in apr_file_writev() on buffered file. PR 40963. [Davi Arnaut <davi haxent.com.br>] diff --git a/file_io/unix/filedup.c b/file_io/unix/filedup.c index 82e2aa774..e9c0d1f65 100644 --- a/file_io/unix/filedup.c +++ b/file_io/unix/filedup.c @@ -55,7 +55,7 @@ static apr_status_t _file_dup(apr_file_t **new_file, #if APR_HAS_THREADS if ((*new_file)->buffered && !(*new_file)->thlock && old_file->thlock) { apr_thread_mutex_create(&((*new_file)->thlock), - APR_THREAD_MUTEX_DEFAULT, p); + APR_THREAD_MUTEX_NESTED, p); } #endif /* As above, only create the buffer if we haven't already @@ -126,7 +126,7 @@ APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file, #if APR_HAS_THREADS if (old_file->thlock) { apr_thread_mutex_create(&((*new_file)->thlock), - APR_THREAD_MUTEX_DEFAULT, p); + APR_THREAD_MUTEX_NESTED, p); apr_thread_mutex_destroy(old_file->thlock); } #endif /* APR_HAS_THREADS */ diff --git a/file_io/unix/open.c b/file_io/unix/open.c index e459a0516..5a5615203 100644 --- a/file_io/unix/open.c +++ b/file_io/unix/open.c @@ -108,7 +108,7 @@ APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, #if APR_HAS_THREADS if ((flag & APR_BUFFERED) && (flag & APR_XTHREAD)) { rv = apr_thread_mutex_create(&thlock, - APR_THREAD_MUTEX_DEFAULT, pool); + APR_THREAD_MUTEX_NESTED, pool); if (rv) { return rv; } @@ -218,7 +218,7 @@ APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file, if ((*file)->flags & APR_XTHREAD) { apr_status_t rv; rv = apr_thread_mutex_create(&((*file)->thlock), - APR_THREAD_MUTEX_DEFAULT, pool); + APR_THREAD_MUTEX_NESTED, pool); if (rv) { return rv; } diff --git a/file_io/unix/readwrite.c b/file_io/unix/readwrite.c index ff69b1051..71fa6d225 100644 --- a/file_io/unix/readwrite.c +++ b/file_io/unix/readwrite.c @@ -43,20 +43,12 @@ APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size apr_uint64_t blocksize; apr_uint64_t size = *nbytes; -#if APR_HAS_THREADS - if (thefile->thlock) { - apr_thread_mutex_lock(thefile->thlock); - } -#endif + file_lock(thefile); if (thefile->direction == 1) { rv = apr_file_flush(thefile); if (rv) { -#if APR_HAS_THREADS - if (thefile->thlock) { - apr_thread_mutex_unlock(thefile->thlock); - } -#endif + file_unlock(thefile); return rv; } thefile->bufpos = 0; @@ -99,11 +91,9 @@ APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size if (*nbytes) { rv = 0; } -#if APR_HAS_THREADS - if (thefile->thlock) { - apr_thread_mutex_unlock(thefile->thlock); - } -#endif + + file_unlock(thefile); + return rv; } else { @@ -161,11 +151,7 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, a int blocksize; int size = *nbytes; -#if APR_HAS_THREADS - if (thefile->thlock) { - apr_thread_mutex_lock(thefile->thlock); - } -#endif + file_lock(thefile); if ( thefile->direction == 0 ) { /* Position file pointer for writing at the offset we are @@ -191,11 +177,8 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, a size -= blocksize; } -#if APR_HAS_THREADS - if (thefile->thlock) { - apr_thread_mutex_unlock(thefile->thlock); - } -#endif + file_unlock(thefile); + return rv; } else { @@ -242,12 +225,15 @@ APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iove apr_size_t nvec, apr_size_t *nbytes) { #ifdef HAVE_WRITEV + apr_status_t rv; int bytes; -#endif + + file_lock(thefile); if (thefile->buffered) { apr_status_t rv = apr_file_flush(thefile); if (rv != APR_SUCCESS) { + file_unlock(thefile); return rv; } if (thefile->direction == 0) { @@ -262,15 +248,17 @@ APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iove } } -#ifdef HAVE_WRITEV if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) { *nbytes = 0; - return errno; + rv = errno; } else { *nbytes = bytes; - return APR_SUCCESS; + rv = APR_SUCCESS; } + + file_unlock(thefile); + return rv; #else *nbytes = vec[0].iov_len; return apr_file_write(thefile, vec[0].iov_base, nbytes); @@ -306,24 +294,29 @@ APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile) APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile) { + apr_status_t rv = APR_SUCCESS; + if (thefile->buffered) { - apr_int64_t written = 0; + file_lock(thefile); if (thefile->direction == 1 && thefile->bufpos) { + apr_int64_t written = 0; do { written = write(thefile->filedes, thefile->buffer, thefile->bufpos); } while (written == (apr_int64_t)-1 && errno == EINTR); if (written == (apr_int64_t)-1) { - return errno; + rv = errno; + } else { + thefile->filePtr += written; + thefile->bufpos = 0; } - thefile->filePtr += written; - thefile->bufpos = 0; } + file_unlock(thefile); } /* There isn't anything to do if we aren't buffering the output * so just return success. */ - return APR_SUCCESS; + return rv; } APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile) diff --git a/file_io/unix/seek.c b/file_io/unix/seek.c index 08ea64a6d..552f8fd1c 100644 --- a/file_io/unix/seek.c +++ b/file_io/unix/seek.c @@ -58,6 +58,8 @@ APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t wh int rc = EINVAL; apr_finfo_t finfo; + file_lock(thefile); + switch (where) { case APR_SET: rc = setptr(thefile, *offset); @@ -75,6 +77,9 @@ APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t wh } *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; + + file_unlock(thefile); + return rc; } else { diff --git a/include/arch/unix/apr_arch_file_io.h b/include/arch/unix/apr_arch_file_io.h index 3906b7cf5..e3c089152 100644 --- a/include/arch/unix/apr_arch_file_io.h +++ b/include/arch/unix/apr_arch_file_io.h @@ -104,6 +104,20 @@ struct apr_file_t { #endif }; +#if APR_HAS_THREADS +#define file_lock(f) do { \ + if ((f)->thlock) \ + apr_thread_mutex_lock((f)->thlock); \ + } while (0) +#define file_unlock(f) do { \ + if ((f)->thlock) \ + apr_thread_mutex_unlock((f)->thlock); \ + } while (0) +#else +#define file_lock(f) do {} while (0) +#define file_unlock(f) do {} while (0) +#endif + struct apr_dir_t { apr_pool_t *pool; char *dirname; |