summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES3
-rw-r--r--file_io/unix/filedup.c4
-rw-r--r--file_io/unix/open.c4
-rw-r--r--file_io/unix/readwrite.c61
-rw-r--r--file_io/unix/seek.c5
-rw-r--r--include/arch/unix/apr_arch_file_io.h14
6 files changed, 53 insertions, 38 deletions
diff --git a/CHANGES b/CHANGES
index a17b846fc..5db9a5d4f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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;