Ideally, we would improve our replacement <sys/socket.h> to define a replacement SOCK_NONBLOCK on all platforms, and teach socket() to honor it as well; but that's a bigger task. In the meantime, if the platform already has SOCK_NONBLOCK, we should honor it when doing a fallback.
* lib/accept4.c (accept4): If SOCK_NONBLOCK is defined, honor it. --- ChangeLog | 3 +++ lib/accept4.c | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6253f9221..f5eda2fa3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2019-08-20 Eric Blake <ebl...@redhat.com> + accept4: Support SOCK_NONBLOCK, if defined + * lib/accept4.c (accept4): If SOCK_NONBLOCK is defined, honor it. + accept4: Fix compilation when native accept4() exists. Reported by Richard W.M. Jones <rjo...@redhat.com> in https://lists.gnu.org/archive/html/bug-gnulib/2019-08/msg00029.html diff --git a/lib/accept4.c b/lib/accept4.c index c6e59c955..9ce78fa96 100644 --- a/lib/accept4.c +++ b/lib/accept4.c @@ -31,6 +31,9 @@ #ifndef SOCK_CLOEXEC # define SOCK_CLOEXEC 0 #endif +#ifndef SOCK_NONBLOCK +# define SOCK_NONBLOCK 0 +#endif int accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) @@ -58,7 +61,7 @@ accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) #endif /* Check the supported flags. */ - if ((flags & ~(SOCK_CLOEXEC | O_TEXT | O_BINARY)) != 0) + if ((flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK | O_TEXT | O_BINARY)) != 0) { errno = EINVAL; return -1; @@ -121,6 +124,22 @@ accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) # endif #endif +#if SOCK_CLOEXEC + if (flags & SOCK_NONBLOCK) + { + int fcntl_flags; + + if ((fcntl_flags = fcntl (fd, F_GETFL, 0)) < 0 + || fcntl (fd, F_SETFL, fcntl_flags | O_NONBLOCK) == -1) + { + int saved_errno = errno; + close (fd); + errno = saved_errno; + return -1; + } + } +#endif + #if O_BINARY if (flags & O_BINARY) set_binary_mode (fd, O_BINARY); -- 2.21.0