unix: simplify open(O_CLOEXEC) feature detection

Platforms that support O_CLOEXEC have supported it for a long time
and don't need feature detection. Libuv can just assume it works as
advertised.

The feature detection was broken for old Linux kernels because they
don't report EINVAL for unknown open() flags, they simply open the
file without setting the FD_CLOEXEC flag.

Libuv could fix that by checking afterwards with fcntl() if the flag
was actually set but it doesn't support kernels that old in the first
place so let's simplify the logic.

Fixes: https://github.com/libuv/libuv/issues/2450
PR-URL: https://github.com/libuv/libuv/pull/2454
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
Ben Noordhuis 2019-09-06 22:49:21 +02:00
parent c898f2e838
commit 1f63e287b6
2 changed files with 15 additions and 34 deletions

View File

@ -30,7 +30,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fcntl.h> /* O_CLOEXEC */
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
@ -51,9 +51,6 @@
#if defined(__APPLE__)
# include <sys/filio.h>
# if defined(O_CLOEXEC)
# define UV__O_CLOEXEC O_CLOEXEC
# endif /* defined(O_CLOEXEC) */
# endif /* defined(__APPLE__) */
@ -73,7 +70,6 @@ extern char** environ;
# include <sys/sysctl.h>
# include <sys/filio.h>
# include <sys/wait.h>
# define UV__O_CLOEXEC O_CLOEXEC
# if defined(__FreeBSD__) && __FreeBSD__ >= 10
# define uv__accept4 accept4
# endif
@ -1005,24 +1001,17 @@ int uv_getrusage(uv_rusage_t* rusage) {
int uv__open_cloexec(const char* path, int flags) {
int err;
#if defined(O_CLOEXEC)
int fd;
#if defined(UV__O_CLOEXEC)
static int no_cloexec;
fd = open(path, flags | O_CLOEXEC);
if (fd == -1)
return UV__ERR(errno);
if (!no_cloexec) {
fd = open(path, flags | UV__O_CLOEXEC);
if (fd != -1)
return fd;
if (errno != EINVAL)
return UV__ERR(errno);
/* O_CLOEXEC not supported. */
no_cloexec = 1;
}
#endif
return fd;
#else /* O_CLOEXEC */
int err;
int fd;
fd = open(path, flags);
if (fd == -1)
@ -1035,6 +1024,7 @@ int uv__open_cloexec(const char* path, int flags) {
}
return fd;
#endif /* O_CLOEXEC */
}
@ -1056,7 +1046,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
static int no_dup3;
if (!no_dup3) {
do
r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
r = uv__dup3(oldfd, newfd, O_CLOEXEC);
while (r == -1 && errno == EBUSY);
if (r != -1)
return r;

View File

@ -255,20 +255,10 @@ 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 */
}
return open(req->path, req->flags | O_CLOEXEC, req->mode);
#else /* O_CLOEXEC */
int r;
if (req->cb != NULL)
uv_rwlock_rdlock(&req->loop->cloexec_lock);
@ -289,6 +279,7 @@ static ssize_t uv__fs_open(uv_fs_t* req) {
uv_rwlock_rdunlock(&req->loop->cloexec_lock);
return r;
#endif /* O_CLOEXEC */
}