From dee86dd5b06897ae3f5ae0107840f3fd2d3916ed Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 18 Jan 2012 15:06:15 +0100 Subject: [PATCH] unix: don't retry close() on EINTR Linux 2.6 always closes the file descriptor, even on EINTR. Retrying the close() call isn't merely useless, it's actively harmful - the file descriptor may have been acquired by another thread. --- src/unix/core.c | 17 ----------------- src/unix/internal.h | 11 ++++++++--- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/unix/core.c b/src/unix/core.c index 55c75152..75c01054 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -790,23 +790,6 @@ int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) { } -int uv__close(int fd) { - int status; - - /* - * Retry on EINTR. You may think this is academic but on linux - * and probably other Unices too, close(2) is interruptible. - * Failing to handle EINTR is a common source of fd leaks. - */ - do { - status = close(fd); - } - while (status == -1 && errno == EINTR); - - return status; -} - - int uv__nonblock(int fd, int set) { #if FIONBIO return ioctl(fd, FIONBIO, &set); diff --git a/src/unix/internal.h b/src/unix/internal.h index 70dca5da..084d2d5c 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -154,14 +154,19 @@ enum { UV_TCP_KEEPALIVE = 0x100 /* Turn on keep-alive. */ }; -int uv__close(int fd); +/* core */ 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); +/* 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 + * useless, it's actively harmful - the file descriptor may have been acquired + * by another thread. + */ +#define uv__close(fd) close(fd) + /* error */ uv_err_code uv_translate_sys_error(int sys_errno); void uv_fatal_error(const int errorno, const char* syscall);