diff --git a/src/wayland-os.c b/src/wayland-os.c index f0f6346e..f1e6c55f 100644 --- a/src/wayland-os.c +++ b/src/wayland-os.c @@ -87,6 +87,34 @@ wl_os_socket_cloexec(int domain, int type, int 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 (retval < 0) + return retval; + + sv[0] = set_cloexec_or_close(sv[0]); + sv[1] = set_cloexec_or_close(sv[1]); + if (sv[0] == -1 || sv[1] == -1) { + close(sv[0]); + close(sv[1]); + return -1; + } + + return 0; +} + #if defined(__FreeBSD__) int wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid) diff --git a/src/wayland-os.h b/src/wayland-os.h index 068fd2fe..42e28007 100644 --- a/src/wayland-os.h +++ b/src/wayland-os.h @@ -32,6 +32,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_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid); diff --git a/tests/client-test.c b/tests/client-test.c index 5585c0cd..83bdead6 100644 --- a/tests/client-test.c +++ b/tests/client-test.c @@ -34,6 +34,7 @@ #include #include +#include "wayland-os.h" #include "wayland-private.h" #include "wayland-server.h" #include "test-runner.h" @@ -97,7 +98,7 @@ TEST(client_destroy_listener) bool user_data_destroyed = false; 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]); @@ -184,7 +185,7 @@ TEST(client_destroy_removes_link) struct client_destroy_listener destroy_listener; 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 aed97a0a..753091c6 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -37,6 +37,7 @@ #include #include +#include "wayland-os.h" #include "wayland-private.h" #include "test-runner.h" #include "test-compositor.h" @@ -48,7 +49,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], WL_BUFFER_DEFAULT_MAX_SIZE); assert(connection); @@ -181,8 +182,8 @@ 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], WL_BUFFER_DEFAULT_MAX_SIZE); assert(data->read_connection); @@ -885,7 +886,7 @@ TEST(request_bogus_size) for (bogus_size = 11; bogus_size >= 0; bogus_size--) { fprintf(stderr, "* bogus size %d\n", bogus_size); - 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/os-wrappers-test.c b/tests/os-wrappers-test.c index 83d99561..36e1ef42 100644 --- a/tests/os-wrappers-test.c +++ b/tests/os-wrappers-test.c @@ -166,7 +166,11 @@ do_os_wrappers_socket_cloexec(int n) * Must have 2 calls if falling back, but must also allow * falling back without a forced fallback. */ +#ifdef SOCK_CLOEXEC assert(wrapped_calls_socket > n); +#else + assert(wrapped_calls_socket == 1); +#endif exec_fd_leak_check(nr_fds); } @@ -240,8 +244,8 @@ 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], WL_BUFFER_DEFAULT_MAX_SIZE); diff --git a/tests/resources-test.c b/tests/resources-test.c index 92707297..5a01785a 100644 --- a/tests/resources-test.c +++ b/tests/resources-test.c @@ -28,6 +28,7 @@ #include #include +#include "wayland-os.h" #include "wayland-server.h" #include "test-runner.h" @@ -40,7 +41,7 @@ TEST(create_resource_tst) int s[2]; uint32_t id; - 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]); @@ -111,7 +112,7 @@ TEST(destroy_res_tst) .notify = &destroy_notify }; - 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]); @@ -159,7 +160,7 @@ TEST(create_resource_with_same_id) int s[2]; uint32_t id; - 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]); @@ -243,7 +244,7 @@ TEST(resource_destroy_iteration) .notify = &resource_destroy_notify }; - 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]);