[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