diff --git a/src/unix/core.c b/src/unix/core.c index 366e94b3..af39fc80 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -825,6 +825,24 @@ int uv__cloexec(int fd, int set) { } +/* This function is not execve-safe, there is a race window + * between the call to dup() and fcntl(FD_CLOEXEC). + */ +int uv__dup(int fd) { + fd = dup(fd); + + if (fd == -1) + return -1; + + if (uv__cloexec(fd, 1)) { + SAVE_ERRNO(uv__close(fd)); + return -1; + } + + return fd; +} + + /* TODO move to uv-common.c? */ size_t uv__strlcpy(char* dst, const char* src, size_t size) { const char *org; diff --git a/src/unix/internal.h b/src/unix/internal.h index 2bdd35cd..3591090d 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -168,6 +168,7 @@ void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle, uv_handle_type type); int uv__nonblock(int fd, int set) __attribute__((unused)); int uv__cloexec(int fd, int set) __attribute__((unused)); int uv__socket(int domain, int type, int protocol); +int uv__dup(int fd); /* We used to handle EINTR in uv__close() but linux 2.6 will have closed the * file descriptor anyway, even on EINTR. Retrying in that case isn't merely