os: wrap accept4(SOCK_CLOEXEC)
authorPekka Paalanen <ppaalanen@gmail.com>
Thu, 22 Mar 2012 12:16:10 +0000 (14:16 +0200)
committerPekka Paalanen <ppaalanen@gmail.com>
Wed, 25 Apr 2012 06:37:42 +0000 (09:37 +0300)
Some system C libraries do not have SOCK_CLOEXEC, and completely miss
accept4(), too. Provide a fallback for this case.

This changes the behaviour: no error messages are printed now for
failing to set CLOEXEC but the file descriptor is closed.

The unit test for this wrapper is NOT included.

Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
configure.ac
src/wayland-os.c
src/wayland-os.h
src/wayland-server.c
tests/os-wrappers-test.c

index 615dfdb..63081e1 100644 (file)
@@ -39,6 +39,8 @@ if test "x$GCC" = "xyes"; then
 fi
 AC_SUBST(GCC_CFLAGS)
 
+AC_CHECK_FUNCS([accept4])
+
 AC_ARG_ENABLE([scanner],
               [AC_HELP_STRING([--disable-scanner],
                               [Disable compilation of wayland-scannner])],
index a8756b6..1185e1d 100644 (file)
@@ -20,6 +20,8 @@
  * OF THIS SOFTWARE.
  */
 
+#define _GNU_SOURCE
+
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <unistd.h>
@@ -27,6 +29,7 @@
 #include <errno.h>
 #include <sys/epoll.h>
 
+#include "../config.h"
 #include "wayland-os.h"
 
 static int
@@ -142,3 +145,20 @@ wl_os_epoll_create_cloexec(void)
        fd = epoll_create(1);
        return set_cloexec_or_close(fd);
 }
+
+int
+wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+       int fd;
+
+#ifdef HAVE_ACCEPT4
+       fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
+       if (fd >= 0)
+               return fd;
+       if (errno != ENOSYS)
+               return -1;
+#endif
+
+       fd = accept(sockfd, addr, addrlen);
+       return set_cloexec_or_close(fd);
+}
index f6827f1..c612975 100644 (file)
@@ -35,6 +35,9 @@ wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags);
 int
 wl_os_epoll_create_cloexec(void);
 
+int
+wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
 
 /*
  * The following are for wayland-os.c and the unit tests.
index 94eb308..e8173fb 100644 (file)
@@ -902,14 +902,8 @@ socket_data(int fd, uint32_t mask, void *data)
        int client_fd;
 
        length = sizeof name;
-       client_fd =
-               accept4(fd, (struct sockaddr *) &name, &length, SOCK_CLOEXEC);
-       if (client_fd < 0 && errno == ENOSYS) {
-               client_fd = accept(fd, (struct sockaddr *) &name, &length);
-               if (client_fd >= 0 && fcntl(client_fd, F_SETFD, FD_CLOEXEC) == -1)
-                       fprintf(stderr, "failed to set FD_CLOEXEC flag on client fd, errno: %d\n", errno);
-       }
-
+       client_fd = wl_os_accept_cloexec(fd, (struct sockaddr *) &name,
+                                        &length);
        if (client_fd < 0)
                fprintf(stderr, "failed to accept, errno: %d\n", errno);
 
index 967eb83..9c4e7b2 100644 (file)
@@ -382,3 +382,5 @@ TEST(os_wrappers_epoll_create_cloexec_fallback)
        init_fallbacks(1);
        do_os_wrappers_epoll_create_cloexec(2);
 }
+
+/* FIXME: add tests for wl_os_accept_cloexec() */