summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPekka Paalanen <ppaalanen@gmail.com>2012-03-22 14:16:10 +0200
committerPekka Paalanen <ppaalanen@gmail.com>2012-04-25 09:37:42 +0300
commitff50f6bfc44bd072aa8806f976718d30468fa2c2 (patch)
tree69a2f98133e4b744acb199bfde73dd3ea6d90cc3
parentb2eaf870cf8e8cb842ba29ea4718b596101252a6 (diff)
os: wrap accept4(SOCK_CLOEXEC)
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>
-rw-r--r--configure.ac2
-rw-r--r--src/wayland-os.c20
-rw-r--r--src/wayland-os.h3
-rw-r--r--src/wayland-server.c10
-rw-r--r--tests/os-wrappers-test.c2
5 files changed, 29 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac
index 615dfdb..63081e1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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])],
diff --git a/src/wayland-os.c b/src/wayland-os.c
index a8756b6..1185e1d 100644
--- a/src/wayland-os.c
+++ b/src/wayland-os.c
@@ -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);
+}
diff --git a/src/wayland-os.h b/src/wayland-os.h
index f6827f1..c612975 100644
--- a/src/wayland-os.h
+++ b/src/wayland-os.h
@@ -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.
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 94eb308..e8173fb 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -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);
diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c
index 967eb83..9c4e7b2 100644
--- a/tests/os-wrappers-test.c
+++ b/tests/os-wrappers-test.c
@@ -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() */