| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright © 2012 Collabora, Ltd. | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  |  * Copyright © 2012 Intel Corporation | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-06-10 02:57:59 -07:00
										 |  |  |  * Permission is hereby granted, free of charge, to any person obtaining | 
					
						
							|  |  |  |  * a copy of this software and associated documentation files (the | 
					
						
							|  |  |  |  * "Software"), to deal in the Software without restriction, including | 
					
						
							|  |  |  |  * without limitation the rights to use, copy, modify, merge, publish, | 
					
						
							|  |  |  |  * distribute, sublicense, and/or sell copies of the Software, and to | 
					
						
							|  |  |  |  * permit persons to whom the Software is furnished to do so, subject to | 
					
						
							|  |  |  |  * the following conditions: | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-06-10 02:57:59 -07:00
										 |  |  |  * The above copyright notice and this permission notice (including the | 
					
						
							|  |  |  |  * next paragraph) shall be included in all copies or substantial | 
					
						
							|  |  |  |  * portions of the Software. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
					
						
							|  |  |  |  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
					
						
							|  |  |  |  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
					
						
							|  |  |  |  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | 
					
						
							|  |  |  |  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | 
					
						
							|  |  |  |  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 
					
						
							|  |  |  |  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
					
						
							|  |  |  |  * SOFTWARE. | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define _GNU_SOURCE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2016-07-18 12:42:25 -05:00
										 |  |  | #include <stdint.h>
 | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | #include <assert.h>
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/socket.h>
 | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | #include <sys/stat.h>
 | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <dlfcn.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							| 
									
										
										
										
											2012-04-23 13:55:55 +03:00
										 |  |  | #include <stdarg.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2012-03-22 15:02:05 +02:00
										 |  |  | #include <sys/epoll.h>
 | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-15 22:44:28 +00:00
										 |  |  | #include "wayland-private.h"
 | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | #include "test-runner.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-15 22:44:28 +00:00
										 |  |  | #include "wayland-os.h"
 | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int fall_back; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int (*real_socket)(int, int, int); | 
					
						
							| 
									
										
										
										
											2012-04-23 13:55:55 +03:00
										 |  |  | static int wrapped_calls_socket; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int (*real_fcntl)(int, int, ...); | 
					
						
							|  |  |  | static int wrapped_calls_fcntl; | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | static ssize_t (*real_recvmsg)(int, struct msghdr *, int); | 
					
						
							|  |  |  | static int wrapped_calls_recvmsg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-22 15:02:05 +02:00
										 |  |  | static int (*real_epoll_create1)(int); | 
					
						
							|  |  |  | static int wrapped_calls_epoll_create1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | static void | 
					
						
							|  |  |  | init_fallbacks(int do_fallbacks) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	fall_back = do_fallbacks; | 
					
						
							|  |  |  | 	real_socket = dlsym(RTLD_NEXT, "socket"); | 
					
						
							| 
									
										
										
										
											2012-04-23 13:55:55 +03:00
										 |  |  | 	real_fcntl = dlsym(RTLD_NEXT, "fcntl"); | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | 	real_recvmsg = dlsym(RTLD_NEXT, "recvmsg"); | 
					
						
							| 
									
										
										
										
											2012-03-22 15:02:05 +02:00
										 |  |  | 	real_epoll_create1 = dlsym(RTLD_NEXT, "epoll_create1"); | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | __attribute__ ((visibility("default"))) int | 
					
						
							|  |  |  | socket(int domain, int type, int protocol) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-23 13:55:55 +03:00
										 |  |  | 	wrapped_calls_socket++; | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (fall_back && (type & SOCK_CLOEXEC)) { | 
					
						
							|  |  |  | 		errno = EINVAL; | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return real_socket(domain, type, protocol); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-23 13:55:55 +03:00
										 |  |  | __attribute__ ((visibility("default"))) int | 
					
						
							|  |  |  | fcntl(int fd, int cmd, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	va_list ap; | 
					
						
							|  |  |  | 	void *arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wrapped_calls_fcntl++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (fall_back && (cmd == F_DUPFD_CLOEXEC)) { | 
					
						
							|  |  |  | 		errno = EINVAL; | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	va_start(ap, cmd); | 
					
						
							|  |  |  | 	arg = va_arg(ap, void*); | 
					
						
							|  |  |  | 	va_end(ap); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return real_fcntl(fd, cmd, arg); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | __attribute__ ((visibility("default"))) ssize_t | 
					
						
							|  |  |  | recvmsg(int sockfd, struct msghdr *msg, int flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	wrapped_calls_recvmsg++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (fall_back && (flags & MSG_CMSG_CLOEXEC)) { | 
					
						
							|  |  |  | 		errno = EINVAL; | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return real_recvmsg(sockfd, msg, flags); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-22 15:02:05 +02:00
										 |  |  | __attribute__ ((visibility("default"))) int | 
					
						
							|  |  |  | epoll_create1(int flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	wrapped_calls_epoll_create1++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (fall_back) { | 
					
						
							|  |  |  | 		wrapped_calls_epoll_create1++; /* epoll_create() not wrapped */ | 
					
						
							|  |  |  | 		errno = EINVAL; | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return real_epoll_create1(flags); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | static void | 
					
						
							|  |  |  | do_os_wrappers_socket_cloexec(int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int fd; | 
					
						
							|  |  |  | 	int nr_fds; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nr_fds = count_open_fds(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* simply create a socket that closes on exec */ | 
					
						
							|  |  |  | 	fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0); | 
					
						
							| 
									
										
										
										
											2012-04-23 12:10:45 +03:00
										 |  |  | 	assert(fd >= 0); | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Must have 2 calls if falling back, but must also allow | 
					
						
							|  |  |  | 	 * falling back without a forced fallback. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2012-04-23 13:55:55 +03:00
										 |  |  | 	assert(wrapped_calls_socket > n); | 
					
						
							| 
									
										
										
										
											2012-03-21 11:11:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	exec_fd_leak_check(nr_fds); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(os_wrappers_socket_cloexec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* normal case */ | 
					
						
							|  |  |  | 	init_fallbacks(0); | 
					
						
							|  |  |  | 	do_os_wrappers_socket_cloexec(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(os_wrappers_socket_cloexec_fallback) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* forced fallback */ | 
					
						
							|  |  |  | 	init_fallbacks(1); | 
					
						
							|  |  |  | 	do_os_wrappers_socket_cloexec(1); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-04-23 13:55:55 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | do_os_wrappers_dupfd_cloexec(int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int base_fd; | 
					
						
							|  |  |  | 	int fd; | 
					
						
							|  |  |  | 	int nr_fds; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nr_fds = count_open_fds(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	base_fd = socket(PF_LOCAL, SOCK_STREAM, 0); | 
					
						
							|  |  |  | 	assert(base_fd >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fd = wl_os_dupfd_cloexec(base_fd, 13); | 
					
						
							|  |  |  | 	assert(fd >= 13); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	close(base_fd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Must have 4 calls if falling back, but must also allow | 
					
						
							|  |  |  | 	 * falling back without a forced fallback. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	assert(wrapped_calls_fcntl > n); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	exec_fd_leak_check(nr_fds); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(os_wrappers_dupfd_cloexec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	init_fallbacks(0); | 
					
						
							|  |  |  | 	do_os_wrappers_dupfd_cloexec(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(os_wrappers_dupfd_cloexec_fallback) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	init_fallbacks(1); | 
					
						
							|  |  |  | 	do_os_wrappers_dupfd_cloexec(3); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct marshal_data { | 
					
						
							|  |  |  | 	struct wl_connection *read_connection; | 
					
						
							|  |  |  | 	struct wl_connection *write_connection; | 
					
						
							|  |  |  | 	int s[2]; | 
					
						
							|  |  |  | 	uint32_t read_mask; | 
					
						
							|  |  |  | 	uint32_t write_mask; | 
					
						
							|  |  |  | 	union { | 
					
						
							|  |  |  | 		int h[3]; | 
					
						
							|  |  |  | 	} value; | 
					
						
							|  |  |  | 	int nr_fds_begin; | 
					
						
							|  |  |  | 	int nr_fds_conn; | 
					
						
							|  |  |  | 	int wrapped_calls; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | setup_marshal_data(struct marshal_data *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	assert(socketpair(AF_UNIX, | 
					
						
							|  |  |  | 			  SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-04 16:54:22 -04:00
										 |  |  | 	data->read_connection = wl_connection_create(data->s[0]); | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | 	assert(data->read_connection); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-04 16:54:22 -04:00
										 |  |  | 	data->write_connection = wl_connection_create(data->s[1]); | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | 	assert(data->write_connection); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2015-05-15 17:12:41 +02:00
										 |  |  | marshal_demarshal(struct marshal_data *data, | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | 		  void (*func)(void), int size, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-06-15 16:09:39 -04:00
										 |  |  | 	struct wl_closure *closure; | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | 	static const int opcode = 4444; | 
					
						
							|  |  |  | 	static struct wl_object sender = { NULL, NULL, 1234 }; | 
					
						
							|  |  |  | 	struct wl_message message = { "test", format, NULL }; | 
					
						
							|  |  |  | 	struct wl_map objects; | 
					
						
							| 
									
										
										
										
											2013-03-08 22:26:12 -06:00
										 |  |  | 	struct wl_object object = { NULL, &func, 1234 }; | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | 	va_list ap; | 
					
						
							|  |  |  | 	uint32_t msg[1] = { 1234 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	va_start(ap, format); | 
					
						
							| 
									
										
										
										
											2012-06-15 16:09:39 -04:00
										 |  |  | 	closure = wl_closure_vmarshal(&sender, opcode, ap, &message); | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | 	va_end(ap); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-15 16:09:39 -04:00
										 |  |  | 	assert(closure); | 
					
						
							|  |  |  | 	assert(wl_closure_send(closure, data->write_connection) == 0); | 
					
						
							|  |  |  | 	wl_closure_destroy(closure); | 
					
						
							| 
									
										
										
										
											2012-10-04 16:54:22 -04:00
										 |  |  | 	assert(wl_connection_flush(data->write_connection) == size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(wl_connection_read(data->read_connection) == size); | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-05 09:52:39 -05:00
										 |  |  | 	wl_map_init(&objects, WL_MAP_SERVER_SIDE); | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | 	object.id = msg[0]; | 
					
						
							| 
									
										
										
										
											2012-06-15 16:09:39 -04:00
										 |  |  | 	closure = wl_connection_demarshal(data->read_connection, | 
					
						
							|  |  |  | 					  size, &objects, &message); | 
					
						
							| 
									
										
										
										
											2014-01-10 13:04:34 -08:00
										 |  |  | 	assert(closure); | 
					
						
							| 
									
										
										
										
											2013-03-08 22:26:12 -06:00
										 |  |  | 	wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, data); | 
					
						
							| 
									
										
										
										
											2012-06-15 16:09:39 -04:00
										 |  |  | 	wl_closure_destroy(closure); | 
					
						
							| 
									
										
										
										
											2012-03-21 16:00:23 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | validate_recvmsg_h(struct marshal_data *data, | 
					
						
							|  |  |  | 		   struct wl_object *object, int fd1, int fd2, int fd3) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct stat buf1, buf2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(fd1 >= 0); | 
					
						
							|  |  |  | 	assert(fd2 >= 0); | 
					
						
							|  |  |  | 	assert(fd3 >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(fd1 != data->value.h[0]); | 
					
						
							|  |  |  | 	assert(fd2 != data->value.h[1]); | 
					
						
							|  |  |  | 	assert(fd3 != data->value.h[2]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(fstat(fd3, &buf1) == 0); | 
					
						
							|  |  |  | 	assert(fstat(data->value.h[2], &buf2) == 0); | 
					
						
							|  |  |  | 	assert(buf1.st_dev == buf2.st_dev); | 
					
						
							|  |  |  | 	assert(buf1.st_ino == buf2.st_ino); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* close the original file descriptors */ | 
					
						
							|  |  |  | 	close(data->value.h[0]); | 
					
						
							|  |  |  | 	close(data->value.h[1]); | 
					
						
							|  |  |  | 	close(data->value.h[2]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* the dup'd (received) fds should still be open */ | 
					
						
							|  |  |  | 	assert(count_open_fds() == data->nr_fds_conn + 3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Must have 2 calls if falling back, but must also allow | 
					
						
							|  |  |  | 	 * falling back without a forced fallback. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	assert(wrapped_calls_recvmsg > data->wrapped_calls); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (data->wrapped_calls == 0 && wrapped_calls_recvmsg > 1) | 
					
						
							|  |  |  | 		printf("recvmsg fell back unforced.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* all fds opened during the test in any way should be gone on exec */ | 
					
						
							|  |  |  | 	exec_fd_leak_check(data->nr_fds_begin); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | do_os_wrappers_recvmsg_cloexec(int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct marshal_data data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data.nr_fds_begin = count_open_fds(); | 
					
						
							|  |  |  | 	data.wrapped_calls = n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	setup_marshal_data(&data); | 
					
						
							|  |  |  | 	data.nr_fds_conn = count_open_fds(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(pipe(data.value.h) >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data.value.h[2] = open("/dev/zero", O_RDONLY); | 
					
						
							|  |  |  | 	assert(data.value.h[2] >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	marshal_demarshal(&data, (void *) validate_recvmsg_h, | 
					
						
							|  |  |  | 			  8, "hhh", data.value.h[0], data.value.h[1], | 
					
						
							|  |  |  | 			  data.value.h[2]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(os_wrappers_recvmsg_cloexec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	init_fallbacks(0); | 
					
						
							|  |  |  | 	do_os_wrappers_recvmsg_cloexec(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(os_wrappers_recvmsg_cloexec_fallback) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	init_fallbacks(1); | 
					
						
							|  |  |  | 	do_os_wrappers_recvmsg_cloexec(1); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-03-22 15:02:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | do_os_wrappers_epoll_create_cloexec(int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int fd; | 
					
						
							|  |  |  | 	int nr_fds; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nr_fds = count_open_fds(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fd = wl_os_epoll_create_cloexec(); | 
					
						
							|  |  |  | 	assert(fd >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef EPOLL_CLOEXEC
 | 
					
						
							|  |  |  | 	assert(wrapped_calls_epoll_create1 == n); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	printf("No epoll_create1.\n"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	exec_fd_leak_check(nr_fds); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(os_wrappers_epoll_create_cloexec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	init_fallbacks(0); | 
					
						
							|  |  |  | 	do_os_wrappers_epoll_create_cloexec(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(os_wrappers_epoll_create_cloexec_fallback) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	init_fallbacks(1); | 
					
						
							|  |  |  | 	do_os_wrappers_epoll_create_cloexec(2); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-03-22 14:16:10 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* FIXME: add tests for wl_os_accept_cloexec() */ |