[PATCH 07/12] wayland-os: Always use CLOEXEC fallbacks on FreeBSD

Philip Withnall philip at tecnocode.co.uk
Fri Feb 15 04:56:59 PST 2013


FreeBSD doesn’t support useful flags like SOCK_CLOEXEC, so we have to suffer
the race condition and always use the fcntl(F_SETFD, FD_CLOEXEC) fallback
on FreeBSD.

This also requires disabling some tests which test whether the fallbacks have
been hit.

Signed-off-by: Philip Withnall <philip at tecnocode.co.uk>
---
 src/wayland-os.c         | 26 ++++++++++++++++++++++++++
 src/wayland-os.h         |  3 +++
 tests/client-test.c      |  3 ++-
 tests/connection-test.c  |  6 +++---
 tests/os-wrappers-test.c | 15 +++++++++++++--
 5 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/src/wayland-os.c b/src/wayland-os.c
index aad6da6..7d69476 100644
--- a/src/wayland-os.c
+++ b/src/wayland-os.c
@@ -66,26 +66,50 @@ wl_os_socket_cloexec(int domain, int type, int protocol)
 {
 	int fd;
 
+#ifdef SOCK_CLOEXEC
 	fd = socket(domain, type | SOCK_CLOEXEC, protocol);
 	if (fd >= 0)
 		return fd;
 	if (errno != EINVAL)
 		return -1;
+#endif
 
 	fd = socket(domain, type, protocol);
 	return set_cloexec_or_close(fd);
 }
 
 int
+wl_os_socketpair_cloexec(int domain, int type, int protocol, int sv[2])
+{
+	int retval;
+
+#ifdef SOCK_CLOEXEC
+	retval = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv);
+	if (retval >= 0)
+		return retval;
+	if (errno != EINVAL)
+		return -1;
+#endif
+
+	retval = socketpair(domain, type, protocol, sv);
+	if (set_cloexec_or_close(sv[0]) < 0 || set_cloexec_or_close(sv[1]) < 0)
+		retval = -1;
+
+	return retval;
+}
+
+int
 wl_os_dupfd_cloexec(int fd, long minfd)
 {
 	int newfd;
 
+#ifdef F_DUPFD_CLOEXEC
 	newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
 	if (newfd >= 0)
 		return newfd;
 	if (errno != EINVAL)
 		return -1;
+#endif
 
 	newfd = fcntl(fd, F_DUPFD, minfd);
 	return set_cloexec_or_close(newfd);
@@ -125,6 +149,7 @@ recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags)
 ssize_t
 wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
 {
+#ifdef MSG_CMSG_CLOEXEC
 	ssize_t len;
 
 	len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC);
@@ -132,6 +157,7 @@ wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
 		return len;
 	if (errno != EINVAL)
 		return -1;
+#endif
 
 	return recvmsg_cloexec_fallback(sockfd, msg, flags);
 }
diff --git a/src/wayland-os.h b/src/wayland-os.h
index b2c3567..0db67e1 100644
--- a/src/wayland-os.h
+++ b/src/wayland-os.h
@@ -27,6 +27,9 @@ int
 wl_os_socket_cloexec(int domain, int type, int protocol);
 
 int
+wl_os_socketpair_cloexec(int domain, int type, int protocol, int sv[2]);
+
+int
 wl_os_dupfd_cloexec(int fd, long minfd);
 
 ssize_t
diff --git a/tests/client-test.c b/tests/client-test.c
index 5cf374d..1d7c7fa 100644
--- a/tests/client-test.c
+++ b/tests/client-test.c
@@ -31,6 +31,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#include "wayland-os.h"
 #include "wayland-server.h"
 #include "wayland-private.h"
 #include "test-runner.h"
@@ -56,7 +57,7 @@ TEST(client_destroy_listener)
 	struct client_destroy_listener a, b;
 	int s[2];
 
-	assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
+	assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0);
 	display = wl_display_create();
 	assert(display);
 	client = wl_client_create(display, s[0]);
diff --git a/tests/connection-test.c b/tests/connection-test.c
index 1ac88d2..ce4cd1a 100644
--- a/tests/connection-test.c
+++ b/tests/connection-test.c
@@ -32,6 +32,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#include "wayland-os.h"
 #include "wayland-private.h"
 #include "test-runner.h"
 
@@ -42,7 +43,7 @@ setup(int *s)
 {
 	struct wl_connection *connection;
 
-	assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
+	assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, s) == 0);
 
 	connection = wl_connection_create(s[0]);
 	assert(connection);
@@ -136,8 +137,7 @@ struct marshal_data {
 static void
 setup_marshal_data(struct marshal_data *data)
 {
-	assert(socketpair(AF_UNIX,
-			  SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
+	assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, data->s) == 0);
 	data->read_connection = wl_connection_create(data->s[0]);
 	assert(data->read_connection);
 	data->write_connection = wl_connection_create(data->s[1]);
diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c
index ca79c5e..af7901c 100644
--- a/tests/os-wrappers-test.c
+++ b/tests/os-wrappers-test.c
@@ -85,10 +85,12 @@ socket(int domain, int type, int protocol)
 {
 	wrapped_calls_socket++;
 
+#ifdef SOCK_CLOEXEC
 	if (fall_back && (type & SOCK_CLOEXEC)) {
 		errno = EINVAL;
 		return -1;
 	}
+#endif
 
 	return real_socket(domain, type, protocol);
 }
@@ -101,10 +103,12 @@ fcntl(int fd, int cmd, ...)
 
 	wrapped_calls_fcntl++;
 
+#ifdef F_DUPFD_CLOEXEC
 	if (fall_back && (cmd == F_DUPFD_CLOEXEC)) {
 		errno = EINVAL;
 		return -1;
 	}
+#endif
 
 	va_start(ap, cmd);
 	arg = va_arg(ap, void*);
@@ -118,10 +122,12 @@ recvmsg(int sockfd, struct msghdr *msg, int flags)
 {
 	wrapped_calls_recvmsg++;
 
+#ifdef MSG_CMSG_CLOEXEC
 	if (fall_back && (flags & MSG_CMSG_CLOEXEC)) {
 		errno = EINVAL;
 		return -1;
 	}
+#endif
 
 	return real_recvmsg(sockfd, msg, flags);
 }
@@ -178,12 +184,14 @@ TEST(os_wrappers_socket_cloexec)
 	do_os_wrappers_socket_cloexec(0);
 }
 
+#ifdef SOCK_CLOEXEC
 TEST(os_wrappers_socket_cloexec_fallback)
 {
 	/* forced fallback */
 	init_fallbacks(1);
 	do_os_wrappers_socket_cloexec(1);
 }
+#endif
 
 static void
 do_os_wrappers_dupfd_cloexec(int n)
@@ -217,11 +225,13 @@ TEST(os_wrappers_dupfd_cloexec)
 	do_os_wrappers_dupfd_cloexec(0);
 }
 
+#ifdef F_DUPFD_CLOEXEC
 TEST(os_wrappers_dupfd_cloexec_fallback)
 {
 	init_fallbacks(1);
 	do_os_wrappers_dupfd_cloexec(3);
 }
+#endif
 
 struct marshal_data {
 	struct wl_connection *read_connection;
@@ -240,8 +250,7 @@ struct marshal_data {
 static void
 setup_marshal_data(struct marshal_data *data)
 {
-	assert(socketpair(AF_UNIX,
-			  SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
+	assert(wl_os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, data->s) == 0);
 
 	data->read_connection = wl_connection_create(data->s[0]);
 	assert(data->read_connection);
@@ -349,11 +358,13 @@ TEST(os_wrappers_recvmsg_cloexec)
 	do_os_wrappers_recvmsg_cloexec(0);
 }
 
+#ifdef MSG_CMSG_CLOEXEC
 TEST(os_wrappers_recvmsg_cloexec_fallback)
 {
 	init_fallbacks(1);
 	do_os_wrappers_recvmsg_cloexec(1);
 }
+#endif
 
 static void
 do_os_wrappers_epoll_create_cloexec(int n)
-- 
1.7.11.7

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 230 bytes
Desc: This is a digitally signed message part
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20130215/08313582/attachment.pgp>


More information about the wayland-devel mailing list