From cb03e3bd26587b851552ad8b54b30600e48ef829 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 10 Oct 2012 02:09:37 +0200 Subject: [PATCH] darwin: work around concurrent write() kernel bug Simultaneously writing from multiple threads to the same file descriptor is not safe on OS X. We already serialized all pwrite() system calls, apply the same workaround to the write() system call. Fixes a node.js test, test/simple/test-fs-sir-writes-alot.js, that was failing because parts of the output file got filled with nul bytes. --- src/unix/fs.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index 1e1c653b..f0bf81af 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -133,24 +133,6 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { } -static ssize_t uv__fs_pwrite(uv_fs_t* req) { -#if defined(__APPLE__) - /* Serialize writes on OS X, concurrent pwrite() calls result in data loss. - * We can't use a per-file descriptor lock, the descriptor may be a dup(). - */ - static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - ssize_t r; - - pthread_mutex_lock(&lock); - r = pwrite(req->file, req->buf, req->len, req->off); - pthread_mutex_unlock(&lock); - - return r; -#else - return pwrite(req->file, req->buf, req->len, req->off); -#endif -} - static ssize_t uv__fs_read(uv_fs_t* req) { if (req->off < 0) return read(req->file, req->buf, req->len); @@ -447,10 +429,27 @@ static ssize_t uv__fs_utime(uv_fs_t* req) { static ssize_t uv__fs_write(uv_fs_t* req) { + ssize_t r; + + /* Serialize writes on OS X, concurrent write() and pwrite() calls result in + * data loss. We can't use a per-file descriptor lock, the descriptor may be + * a dup(). + */ +#if defined(__APPLE__) + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&lock); +#endif + if (req->off < 0) - return write(req->file, req->buf, req->len); + r = write(req->file, req->buf, req->len); else - return uv__fs_pwrite(req); + r = pwrite(req->file, req->buf, req->len, req->off); + +#if defined(__APPLE__) + pthread_mutex_unlock(&lock); +#endif + + return r; }