unix: clean up uv_fs_open() O_CLOEXEC logic

Move the logic out of uv__fs_work() and into a function of its own.

PR-URL: https://github.com/libuv/libuv/pull/326
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
Ben Noordhuis 2015-04-21 03:34:55 +02:00
parent 1f711e4d6d
commit 202195c2f4

View File

@ -202,6 +202,44 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
} }
static ssize_t uv__fs_open(uv_fs_t* req) {
static int no_cloexec_support;
int r;
/* Try O_CLOEXEC before entering locks */
if (no_cloexec_support == 0) {
#ifdef O_CLOEXEC
r = open(req->path, req->flags | O_CLOEXEC, req->mode);
if (r >= 0)
return r;
if (errno != EINVAL)
return r;
no_cloexec_support = 1;
#endif /* O_CLOEXEC */
}
if (req->cb != NULL)
uv_rwlock_rdlock(&req->loop->cloexec_lock);
r = open(req->path, req->flags, req->mode);
/* In case of failure `uv__cloexec` will leave error in `errno`,
* so it is enough to just set `r` to `-1`.
*/
if (r >= 0 && uv__cloexec(r, 1) != 0) {
r = uv__close(r);
if (r != 0 && r != -EINPROGRESS)
abort();
r = -1;
}
if (req->cb != NULL)
uv_rwlock_rdunlock(&req->loop->cloexec_lock);
return r;
}
static ssize_t uv__fs_read(uv_fs_t* req) { static ssize_t uv__fs_read(uv_fs_t* req) {
#if defined(__linux__) #if defined(__linux__)
static int no_preadv; static int no_preadv;
@ -743,9 +781,6 @@ static void uv__fs_work(struct uv__work* w) {
int retry_on_eintr; int retry_on_eintr;
uv_fs_t* req; uv_fs_t* req;
ssize_t r; ssize_t r;
#ifdef O_CLOEXEC
static int no_cloexec_support;
#endif /* O_CLOEXEC */
req = container_of(w, uv_fs_t, work_req); req = container_of(w, uv_fs_t, work_req);
retry_on_eintr = !(req->fs_type == UV_FS_CLOSE); retry_on_eintr = !(req->fs_type == UV_FS_CLOSE);
@ -774,6 +809,7 @@ static void uv__fs_work(struct uv__work* w) {
X(LINK, link(req->path, req->new_path)); X(LINK, link(req->path, req->new_path));
X(MKDIR, mkdir(req->path, req->mode)); X(MKDIR, mkdir(req->path, req->mode));
X(MKDTEMP, uv__fs_mkdtemp(req)); X(MKDTEMP, uv__fs_mkdtemp(req));
X(OPEN, uv__fs_open(req));
X(READ, uv__fs_read(req)); X(READ, uv__fs_read(req));
X(SCANDIR, uv__fs_scandir(req)); X(SCANDIR, uv__fs_scandir(req));
X(READLINK, uv__fs_readlink(req)); X(READLINK, uv__fs_readlink(req));
@ -785,41 +821,10 @@ static void uv__fs_work(struct uv__work* w) {
X(UNLINK, unlink(req->path)); X(UNLINK, unlink(req->path));
X(UTIME, uv__fs_utime(req)); X(UTIME, uv__fs_utime(req));
X(WRITE, uv__fs_write(req)); X(WRITE, uv__fs_write(req));
case UV_FS_OPEN:
#ifdef O_CLOEXEC
/* Try O_CLOEXEC before entering locks */
if (!no_cloexec_support) {
r = open(req->path, req->flags | O_CLOEXEC, req->mode);
if (r >= 0)
break;
if (errno != EINVAL)
break;
no_cloexec_support = 1;
}
#endif /* O_CLOEXEC */
if (req->cb != NULL)
uv_rwlock_rdlock(&req->loop->cloexec_lock);
r = open(req->path, req->flags, req->mode);
/*
* In case of failure `uv__cloexec` will leave error in `errno`,
* so it is enough to just set `r` to `-1`.
*/
if (r >= 0 && uv__cloexec(r, 1) != 0) {
r = uv__close(r);
if (r != 0 && r != -EINPROGRESS)
abort();
r = -1;
}
if (req->cb != NULL)
uv_rwlock_rdunlock(&req->loop->cloexec_lock);
break;
default: abort(); default: abort();
} }
#undef X #undef X
} } while (r == -1 && errno == EINTR && retry_on_eintr);
while (r == -1 && errno == EINTR && retry_on_eintr);
if (r == -1) if (r == -1)
req->result = -errno; req->result = -errno;