xref: /xnu-11215.41.3/tests/poll.c (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
1*33de042dSApple OSS Distributions #ifdef T_NAMESPACE
2*33de042dSApple OSS Distributions #undef T_NAMESPACE
3*33de042dSApple OSS Distributions #endif
4*33de042dSApple OSS Distributions #include <darwintest.h>
5*33de042dSApple OSS Distributions 
6*33de042dSApple OSS Distributions #include <dispatch/dispatch.h>
7*33de042dSApple OSS Distributions #include <fcntl.h>
8*33de042dSApple OSS Distributions #include <mach/mach.h>
9*33de042dSApple OSS Distributions #include <poll.h>
10*33de042dSApple OSS Distributions #include <stdint.h>
11*33de042dSApple OSS Distributions #include <unistd.h>
12*33de042dSApple OSS Distributions 
13*33de042dSApple OSS Distributions T_GLOBAL_META(T_META_NAMESPACE("xnu.poll"),
14*33de042dSApple OSS Distributions     T_META_RUN_CONCURRENTLY(true));
15*33de042dSApple OSS Distributions 
16*33de042dSApple OSS Distributions #define SLEEP_TIME_SECS 1
17*33de042dSApple OSS Distributions #define POLL_TIMEOUT_MS 1800
18*33de042dSApple OSS Distributions static_assert(POLL_TIMEOUT_MS > (SLEEP_TIME_SECS * 1000),
19*33de042dSApple OSS Distributions     "poll timeout should be longer than sleep time");
20*33de042dSApple OSS Distributions 
21*33de042dSApple OSS Distributions /*
22*33de042dSApple OSS Distributions  * This matches the behavior of other UNIXes, but is under-specified in POSIX.
23*33de042dSApple OSS Distributions  *
24*33de042dSApple OSS Distributions  * See <rdar://problem/28372390>.
25*33de042dSApple OSS Distributions  */
26*33de042dSApple OSS Distributions T_DECL(sleep_with_no_fds,
27*33de042dSApple OSS Distributions     "poll() called with no fds provided should act like sleep", T_META_TAG_VM_PREFERRED)
28*33de042dSApple OSS Distributions {
29*33de042dSApple OSS Distributions 	uint64_t begin_time, sleep_time, poll_time;
30*33de042dSApple OSS Distributions 	struct pollfd pfd = { .fd = 0, .events = 0, .revents = 0 };
31*33de042dSApple OSS Distributions 
32*33de042dSApple OSS Distributions 	begin_time = mach_absolute_time();
33*33de042dSApple OSS Distributions 	sleep(SLEEP_TIME_SECS);
34*33de042dSApple OSS Distributions 	sleep_time = mach_absolute_time() - begin_time;
35*33de042dSApple OSS Distributions 	T_LOG("sleep(%d) ~= %llu mach absolute time units", SLEEP_TIME_SECS, sleep_time);
36*33de042dSApple OSS Distributions 
37*33de042dSApple OSS Distributions 	begin_time = mach_absolute_time();
38*33de042dSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(poll(&pfd, 0, POLL_TIMEOUT_MS),
39*33de042dSApple OSS Distributions 	    "poll() with 0 events and timeout %d ms", POLL_TIMEOUT_MS);
40*33de042dSApple OSS Distributions 	poll_time = mach_absolute_time() - begin_time;
41*33de042dSApple OSS Distributions 
42*33de042dSApple OSS Distributions 	T_EXPECT_GT(poll_time, sleep_time,
43*33de042dSApple OSS Distributions 	    "poll(... %d) should wait longer than sleep(1)", POLL_TIMEOUT_MS);
44*33de042dSApple OSS Distributions }
45*33de042dSApple OSS Distributions 
46*33de042dSApple OSS Distributions #define LAUNCHD_PATH "/sbin/launchd"
47*33de042dSApple OSS Distributions #define PIPE_DIR_TIMEOUT_SECS 1
48*33de042dSApple OSS Distributions 
49*33de042dSApple OSS Distributions /*
50*33de042dSApple OSS Distributions  * See <rdar://problem/28539155>.
51*33de042dSApple OSS Distributions  */
52*33de042dSApple OSS Distributions T_DECL(directories,
53*33de042dSApple OSS Distributions     "poll() with directories should return an error", T_META_TAG_VM_PREFERRED)
54*33de042dSApple OSS Distributions {
55*33de042dSApple OSS Distributions 	int file, dir, pipes[2];
56*33de042dSApple OSS Distributions 	struct pollfd pfd[] = {
57*33de042dSApple OSS Distributions 		{ .events = POLLIN },
58*33de042dSApple OSS Distributions 		{ .events = POLLIN },
59*33de042dSApple OSS Distributions 		{ .events = POLLIN },
60*33de042dSApple OSS Distributions 	};
61*33de042dSApple OSS Distributions 
62*33de042dSApple OSS Distributions 	file = open(LAUNCHD_PATH, O_RDONLY | O_NONBLOCK);
63*33de042dSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(file, "open(%s)", LAUNCHD_PATH);
64*33de042dSApple OSS Distributions 	dir = open(".", O_RDONLY | O_NONBLOCK);
65*33de042dSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(dir, "open(\".\")");
66*33de042dSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(pipe(pipes), NULL);
67*33de042dSApple OSS Distributions 
68*33de042dSApple OSS Distributions 	/* just directory */
69*33de042dSApple OSS Distributions 	pfd[0].fd = dir;
70*33de042dSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(poll(pfd, 1, -1), "poll() with a directory");
71*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL,
72*33de042dSApple OSS Distributions 	    "directory should be an invalid event");
73*33de042dSApple OSS Distributions 
74*33de042dSApple OSS Distributions 	/* file and directory */
75*33de042dSApple OSS Distributions 	pfd[0].fd = file; pfd[0].revents = 0;
76*33de042dSApple OSS Distributions 	pfd[1].fd = dir; pfd[1].revents = 0;
77*33de042dSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1),
78*33de042dSApple OSS Distributions 	    "poll() with a file and directory");
79*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable");
80*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLNVAL,
81*33de042dSApple OSS Distributions 	    "directory should be an invalid event");
82*33de042dSApple OSS Distributions 
83*33de042dSApple OSS Distributions 	/* directory and file */
84*33de042dSApple OSS Distributions 	pfd[0].fd = dir; pfd[0].revents = 0;
85*33de042dSApple OSS Distributions 	pfd[1].fd = file; pfd[1].revents = 0;
86*33de042dSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1),
87*33de042dSApple OSS Distributions 	    "poll() with a directory and a file");
88*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL,
89*33de042dSApple OSS Distributions 	    "directory should be an invalid event");
90*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLIN, "file should be readable");
91*33de042dSApple OSS Distributions 
92*33de042dSApple OSS Distributions 	/* file and pipe */
93*33de042dSApple OSS Distributions 	pfd[0].fd = file; pfd[0].revents = 0;
94*33de042dSApple OSS Distributions 	pfd[1].fd = pipes[0]; pfd[0].revents = 0;
95*33de042dSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1),
96*33de042dSApple OSS Distributions 	    "poll() with a file and pipe");
97*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable");
98*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_FALSE(pfd[1].revents & POLLIN,
99*33de042dSApple OSS Distributions 	    "pipe should not be readable");
100*33de042dSApple OSS Distributions 
101*33de042dSApple OSS Distributions 	/* file, directory, and pipe */
102*33de042dSApple OSS Distributions 	pfd[0].fd = file; pfd[0].revents = 0;
103*33de042dSApple OSS Distributions 	pfd[1].fd = dir; pfd[1].revents = 0;
104*33de042dSApple OSS Distributions 	pfd[2].fd = pipes[0]; pfd[2].revents = 0;
105*33de042dSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(poll(pfd, 3, -1),
106*33de042dSApple OSS Distributions 	    "poll() with a file, directory, and pipe");
107*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable");
108*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLNVAL,
109*33de042dSApple OSS Distributions 	    "directory should be an invalid event");
110*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_FALSE(pfd[2].revents & POLLIN, "pipe should not be readable");
111*33de042dSApple OSS Distributions 
112*33de042dSApple OSS Distributions 	/* directory and pipe */
113*33de042dSApple OSS Distributions 	__block bool timed_out = true;
114*33de042dSApple OSS Distributions 	pfd[0].fd = dir; pfd[0].revents = 0;
115*33de042dSApple OSS Distributions 	pfd[1].fd = pipes[0]; pfd[1].revents = 0;
116*33de042dSApple OSS Distributions 	dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
117*33de042dSApple OSS Distributions 	    PIPE_DIR_TIMEOUT_SECS * NSEC_PER_SEC),
118*33de042dSApple OSS Distributions 	    dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
119*33de042dSApple OSS Distributions 		T_ASSERT_FALSE(timed_out, "poll timed out after %d seconds",
120*33de042dSApple OSS Distributions 		PIPE_DIR_TIMEOUT_SECS);
121*33de042dSApple OSS Distributions 	});
122*33de042dSApple OSS Distributions 
123*33de042dSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(poll(pfd, 3, -1),
124*33de042dSApple OSS Distributions 	    "poll() with a directory and pipe");
125*33de042dSApple OSS Distributions 	timed_out = false;
126*33de042dSApple OSS Distributions 
127*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL,
128*33de042dSApple OSS Distributions 	    "directory should be an invalid event");
129*33de042dSApple OSS Distributions 	T_QUIET; T_EXPECT_FALSE(pfd[1].revents & POLLIN, "pipe should not be readable");
130*33de042dSApple OSS Distributions }
131*33de042dSApple OSS Distributions 
132*33de042dSApple OSS Distributions #define PRIVATE
133*33de042dSApple OSS Distributions #include <libproc.h>
134*33de042dSApple OSS Distributions 
135*33de042dSApple OSS Distributions static void *
leak_thread(void * ptr)136*33de042dSApple OSS Distributions leak_thread(void *ptr)
137*33de042dSApple OSS Distributions {
138*33de042dSApple OSS Distributions 	T_LOG("Trying to find kevent kernel pointer...\n");
139*33de042dSApple OSS Distributions 
140*33de042dSApple OSS Distributions 	unsigned char *buffer = (unsigned char*) malloc(16392 * 8);
141*33de042dSApple OSS Distributions 
142*33de042dSApple OSS Distributions 	while (1) {
143*33de042dSApple OSS Distributions 		memset(buffer, 0, 16392 * 8);
144*33de042dSApple OSS Distributions 
145*33de042dSApple OSS Distributions 		// Dump the kevent udatas for self
146*33de042dSApple OSS Distributions 		int ret = proc_list_uptrs(getpid(), buffer, 16392 * 8);
147*33de042dSApple OSS Distributions 
148*33de042dSApple OSS Distributions 		if (ret > 0) {
149*33de042dSApple OSS Distributions 			T_LOG("udata pointers returned: %d\n", ret);
150*33de042dSApple OSS Distributions 			uint64_t *ptrs = (uint64_t*) buffer;
151*33de042dSApple OSS Distributions 			for (int i = 0; i < ret; i++) {
152*33de042dSApple OSS Distributions 				T_EXPECT_EQ(ptrs[i] & 0xffffff0000000000, 0, "kptr? -> 0x%llx\n", ptrs[i]);
153*33de042dSApple OSS Distributions 			}
154*33de042dSApple OSS Distributions 			break;
155*33de042dSApple OSS Distributions 		}
156*33de042dSApple OSS Distributions 	}
157*33de042dSApple OSS Distributions 
158*33de042dSApple OSS Distributions 	free(buffer);
159*33de042dSApple OSS Distributions 	return NULL;
160*33de042dSApple OSS Distributions }
161*33de042dSApple OSS Distributions 
162*33de042dSApple OSS Distributions T_DECL(poll_dont_leak_kernel_pointers, "poll and proc_pidinfo should not leak kernel pointers", T_META_TAG_VM_PREFERRED)
163*33de042dSApple OSS Distributions {
164*33de042dSApple OSS Distributions 	pthread_t thr;
165*33de042dSApple OSS Distributions 	pthread_create(&thr, NULL, *leak_thread, (void *) NULL);
166*33de042dSApple OSS Distributions 
167*33de042dSApple OSS Distributions 	struct pollfd fds[2] = {};
168*33de042dSApple OSS Distributions 	fds[0].fd = STDERR_FILENO;
169*33de042dSApple OSS Distributions 	fds[0].events = POLLERR | POLLHUP;
170*33de042dSApple OSS Distributions 	fds[0].revents = POLLERR;
171*33de042dSApple OSS Distributions 	fds[1].fd = STDOUT_FILENO;
172*33de042dSApple OSS Distributions 	fds[1].events = POLLERR | POLLHUP;
173*33de042dSApple OSS Distributions 	fds[1].revents = POLLERR;
174*33de042dSApple OSS Distributions 
175*33de042dSApple OSS Distributions 	//int poll_nocancel(struct pollfd *fds, u_int nfds, int timeout)
176*33de042dSApple OSS Distributions 	poll(fds, 2, 5000);
177*33de042dSApple OSS Distributions 
178*33de042dSApple OSS Distributions 	pthread_join(thr, NULL);
179*33de042dSApple OSS Distributions }
180