From 067473ed5cbc247d0f12473bd0e9878b1c5f247d Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Tue, 4 Feb 2020 16:36:59 +0100 Subject: [PATCH] linux: simplify uv__accept() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assume the presence of the accept4() system call on Linux. It was added in 2.6.28 and our baseline is 2.6.32. That lets us get rid of the system call wrapper and the fallback logic in uv__accept(). PR-URL: https://github.com/libuv/libuv/pull/2665 Reviewed-By: Santiago Gimeno Reviewed-By: Saúl Ibarra Corretgé --- src/unix/core.c | 63 +++++++++++++-------------------------- src/unix/linux-syscalls.c | 45 ---------------------------- src/unix/linux-syscalls.h | 1 - 3 files changed, 20 insertions(+), 89 deletions(-) diff --git a/src/unix/core.c b/src/unix/core.c index 7475da58..2bf35b78 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -71,17 +71,12 @@ extern char** environ; # include # include # include -# if defined(__FreeBSD__) +# if defined(__FreeBSD__) || defined(__linux__) # define uv__accept4 accept4 # endif # if defined(__NetBSD__) # define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d)) # endif -# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \ - defined(__NetBSD__) || defined(__OpenBSD__) -# define UV__SOCK_NONBLOCK SOCK_NONBLOCK -# define UV__SOCK_CLOEXEC SOCK_CLOEXEC -# endif #endif #if defined(__ANDROID_API__) && __ANDROID_API__ < 21 @@ -469,50 +464,32 @@ int uv__accept(int sockfd) { int peerfd; int err; + (void) &err; assert(sockfd >= 0); - while (1) { -#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) - static int no_accept4; + do +#ifdef uv__accept4 + peerfd = uv__accept4(sockfd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); +#else + peerfd = accept(sockfd, NULL, NULL); +#endif + while (peerfd == -1 && errno == EINTR); - if (no_accept4) - goto skip; + if (peerfd == -1) + return UV__ERR(errno); - peerfd = uv__accept4(sockfd, - NULL, - NULL, - UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC); - if (peerfd != -1) - return peerfd; +#ifndef uv__accept4 + err = uv__cloexec(peerfd, 1); + if (err == 0) + err = uv__nonblock(peerfd, 1); - if (errno == EINTR) - continue; - - if (errno != ENOSYS) - return UV__ERR(errno); - - no_accept4 = 1; -skip: + if (err != 0) { + uv__close(peerfd); + return err; + } #endif - peerfd = accept(sockfd, NULL, NULL); - if (peerfd == -1) { - if (errno == EINTR) - continue; - return UV__ERR(errno); - } - - err = uv__cloexec(peerfd, 1); - if (err == 0) - err = uv__nonblock(peerfd, 1); - - if (err) { - uv__close(peerfd); - return err; - } - - return peerfd; - } + return peerfd; } diff --git a/src/unix/linux-syscalls.c b/src/unix/linux-syscalls.c index 95038786..476af66f 100644 --- a/src/unix/linux-syscalls.c +++ b/src/unix/linux-syscalls.c @@ -33,12 +33,6 @@ # endif #endif -#if defined(__i386__) -# ifndef __NR_socketcall -# define __NR_socketcall 102 -# endif -#endif - #if defined(__arm__) # if defined(__thumb__) || defined(__ARM_EABI__) # define UV_SYSCALL_BASE 0 @@ -47,16 +41,6 @@ # endif #endif /* __arm__ */ -#ifndef __NR_accept4 -# if defined(__x86_64__) -# define __NR_accept4 288 -# elif defined(__i386__) - /* Nothing. Handled through socketcall(). */ -# elif defined(__arm__) -# define __NR_accept4 (UV_SYSCALL_BASE + 366) -# endif -#endif /* __NR_accept4 */ - #ifndef __NR_eventfd # if defined(__x86_64__) # define __NR_eventfd 284 @@ -219,35 +203,6 @@ # endif #endif /* __NR_getrandom */ -int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { -#if defined(__i386__) - unsigned long args[4]; - int r; - - args[0] = (unsigned long) fd; - args[1] = (unsigned long) addr; - args[2] = (unsigned long) addrlen; - args[3] = (unsigned long) flags; - - r = syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args); - - /* socketcall() raises EINVAL when SYS_ACCEPT4 is not supported but so does - * a bad flags argument. Try to distinguish between the two cases. - */ - if (r == -1) - if (errno == EINVAL) - if ((flags & ~(UV__SOCK_CLOEXEC|UV__SOCK_NONBLOCK)) == 0) - errno = ENOSYS; - - return r; -#elif defined(__NR_accept4) - return syscall(__NR_accept4, fd, addr, addrlen, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - int uv__eventfd(unsigned int count) { #if defined(__NR_eventfd) return syscall(__NR_eventfd, count); diff --git a/src/unix/linux-syscalls.h b/src/unix/linux-syscalls.h index b7729b82..05040b1f 100644 --- a/src/unix/linux-syscalls.h +++ b/src/unix/linux-syscalls.h @@ -123,7 +123,6 @@ struct uv__mmsghdr { unsigned int msg_len; }; -int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags); int uv__eventfd(unsigned int count); int uv__eventfd2(unsigned int count, int flags); int uv__inotify_init(void);