Fix: Tests: leaking epoll fd
[lttng-tools.git] / tests / regression / kernel / select_poll_epoll.c
CommitLineData
9d16b343
MJ
1/*
2 * Copyright (C) 2016 Julien Desfossez <jdesfossez@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
a0b1f42c
JD
8#include <stdio.h>
9#include <poll.h>
10#include <signal.h>
11#include <unistd.h>
12#include <sys/syscall.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <fcntl.h>
16#include <stdlib.h>
17#include <string.h>
18#include <stddef.h>
19#include <sys/select.h>
20#include <sys/epoll.h>
21#include <popt.h>
22#include <sys/time.h>
23#include <sys/resource.h>
24#include <limits.h>
25#include <pthread.h>
26#include <sys/mman.h>
389fbf04 27#include <common/compat/time.h>
a0b1f42c
JD
28
29#define BUF_SIZE 256
30#define NB_FD 1
31#define MAX_FDS 2047
32#define NR_ITER 1000 /* for stress-tests */
33
34#define MIN_NR_FDS 5 /* the minimum number of open FDs required for the test to run */
35#define BIG_SELECT_FD 1022
36
37#define MSEC_PER_USEC 1000
38#define MSEC_PER_NSEC (MSEC_PER_USEC * 1000)
39
40static int timeout; /* seconds, -1 to disable */
44a411a6 41static volatile int stop_thread;
a0b1f42c
JD
42static int wait_fd;
43
44struct ppoll_thread_data {
45 struct pollfd *ufds;
46 int value;
47};
48
f12eb9c1 49static
a0b1f42c
JD
50void test_select_big(void)
51{
52 fd_set rfds, wfds, exfds;
53 struct timeval tv;
54 int ret;
55 int fd2;
56 char buf[BUF_SIZE];
57
58 FD_ZERO(&rfds);
59 FD_ZERO(&wfds);
60 FD_ZERO(&exfds);
61
62 fd2 = dup2(wait_fd, BIG_SELECT_FD);
63 if (fd2 < 0) {
64 perror("dup2");
65 goto end;
66 }
67 FD_SET(fd2, &rfds);
68
69 tv.tv_sec = 0;
70 tv.tv_usec = timeout * MSEC_PER_USEC;
71
72 if (timeout > 0) {
73 ret = select(fd2 + 1, &rfds, &wfds, &exfds, &tv);
74 } else {
75 ret = select(fd2 + 1, &rfds, &wfds, &exfds, NULL);
76 }
77
78 if (ret == -1) {
79 perror("select()");
80 } else if (ret) {
81 printf("# [select] data available\n");
82 ret = read(wait_fd, buf, BUF_SIZE);
83 if (ret < 0) {
84 perror("[select] read");
85 }
86 } else {
87 printf("# [select] timeout\n");
88 }
89
90 ret = close(BIG_SELECT_FD);
91 if (ret) {
92 perror("close");
93 }
94
95end:
96 return;
97}
98
f12eb9c1 99static
a0b1f42c
JD
100void test_pselect(void)
101{
102 fd_set rfds;
103 struct timespec tv;
104 int ret;
105 char buf[BUF_SIZE];
106
107 FD_ZERO(&rfds);
108 FD_SET(wait_fd, &rfds);
109
110 tv.tv_sec = 0;
111 tv.tv_nsec = timeout * MSEC_PER_NSEC;
112
113 if (timeout > 0) {
114 ret = pselect(1, &rfds, NULL, NULL, &tv, NULL);
115 } else {
116 ret = pselect(1, &rfds, NULL, NULL, NULL, NULL);
117 }
118
119 if (ret == -1) {
120 perror("pselect()");
121 } else if (ret) {
122 printf("# [pselect] data available\n");
123 ret = read(wait_fd, buf, BUF_SIZE);
124 if (ret < 0) {
125 perror("[pselect] read");
126 }
127 } else {
128 printf("# [pselect] timeout\n");
129 }
130
131}
132
f12eb9c1 133static
a0b1f42c
JD
134void test_select(void)
135{
136 fd_set rfds;
137 struct timeval tv;
138 int ret;
139 char buf[BUF_SIZE];
140
141 FD_ZERO(&rfds);
142 FD_SET(wait_fd, &rfds);
143
144 tv.tv_sec = 0;
145 tv.tv_usec = timeout * MSEC_PER_USEC;
146
147 if (timeout > 0) {
148 ret = select(1, &rfds, NULL, NULL, &tv);
149 } else {
150 ret = select(1, &rfds, NULL, NULL, NULL);
151 }
152
153 if (ret == -1) {
154 perror("select()");
155 } else if (ret) {
156 printf("# [select] data available\n");
157 ret = read(wait_fd, buf, BUF_SIZE);
158 if (ret < 0) {
159 perror("[select] read");
160 }
161 } else {
162 printf("# [select] timeout\n");
163 }
164
165}
166
f12eb9c1 167static
a0b1f42c
JD
168void test_poll(void)
169{
170 struct pollfd ufds[NB_FD];
171 char buf[BUF_SIZE];
172 int ret;
173
174 ufds[0].fd = wait_fd;
175 ufds[0].events = POLLIN|POLLPRI;
176
177 ret = poll(ufds, 1, timeout);
178
179 if (ret < 0) {
180 perror("poll");
181 } else if (ret > 0) {
182 printf("# [poll] data available\n");
183 ret = read(wait_fd, buf, BUF_SIZE);
184 if (ret < 0) {
185 perror("[poll] read");
186 }
187 } else {
188 printf("# [poll] timeout\n");
189 }
190}
191
f12eb9c1 192static
a0b1f42c
JD
193void test_ppoll(void)
194{
195 struct pollfd ufds[NB_FD];
196 char buf[BUF_SIZE];
197 int ret;
198 struct timespec ts;
199
200 ufds[0].fd = wait_fd;
201 ufds[0].events = POLLIN|POLLPRI;
202
203 if (timeout > 0) {
204 ts.tv_sec = 0;
205 ts.tv_nsec = timeout * MSEC_PER_NSEC;
206 ret = ppoll(ufds, 1, &ts, NULL);
207 } else {
208 ret = ppoll(ufds, 1, NULL, NULL);
209 }
210
211
212 if (ret < 0) {
213 perror("ppoll");
214 } else if (ret > 0) {
215 printf("# [ppoll] data available\n");
216 ret = read(wait_fd, buf, BUF_SIZE);
217 if (ret < 0) {
218 perror("[ppoll] read");
219 }
220 } else {
221 printf("# [ppoll] timeout\n");
222 }
223}
224
f12eb9c1 225static
a0b1f42c
JD
226void test_ppoll_big(void)
227{
228 struct pollfd ufds[MAX_FDS];
229 char buf[BUF_SIZE];
230 int ret, i, fds[MAX_FDS];
231
232 for (i = 0; i < MAX_FDS; i++) {
233 fds[i] = dup(wait_fd);
234 if (fds[i] < 0) {
235 perror("dup");
236 }
237 ufds[i].fd = fds[i];
238 ufds[i].events = POLLIN|POLLPRI;
239 }
240
241 ret = ppoll(ufds, MAX_FDS, NULL, NULL);
242
243 if (ret < 0) {
244 perror("ppoll");
245 } else if (ret > 0) {
246 printf("# [ppoll] data available\n");
247 ret = read(wait_fd, buf, BUF_SIZE);
248 if (ret < 0) {
249 perror("[ppoll] read");
250 }
251 } else {
252 printf("# [ppoll] timeout\n");
253 }
254
255 for (i = 0; i < MAX_FDS; i++) {
256 ret = close(fds[i]);
257 if (ret != 0) {
258 perror("close");
259 }
260 }
261
262 return;
263}
264
f12eb9c1 265static
a0b1f42c
JD
266void test_epoll(void)
267{
268 int ret, epollfd;
269 char buf[BUF_SIZE];
270 struct epoll_event epoll_event;
271
272 epollfd = epoll_create(NB_FD);
273 if (epollfd < 0) {
274 perror("[epoll] create");
275 goto end;
276 }
277
278 epoll_event.events = EPOLLIN | EPOLLPRI | EPOLLET;
279 epoll_event.data.fd = wait_fd;
280 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, wait_fd, &epoll_event);
281 if (ret < 0) {
282 perror("[epoll] add");
5305e823 283 goto error;
a0b1f42c
JD
284 }
285
286 if (timeout > 0) {
287 ret = epoll_wait(epollfd, &epoll_event, 1, timeout);
288 } else {
289 ret = epoll_wait(epollfd, &epoll_event, 1, -1);
290 }
291
292 if (ret == 1) {
293 printf("# [epoll] data available\n");
294 ret = read(wait_fd, buf, BUF_SIZE);
295 if (ret < 0) {
296 perror("[epoll] read");
297 }
298 } else if (ret == 0) {
299 printf("# [epoll] timeout\n");
300 } else {
301 perror("epoll_wait");
302 }
303
5305e823
FD
304error:
305 close(epollfd);
a0b1f42c
JD
306end:
307 return;
308}
309
f12eb9c1 310static
a0b1f42c
JD
311void test_pepoll(void)
312{
313 int ret, epollfd;
314 char buf[BUF_SIZE];
315 struct epoll_event epoll_event;
316
317 epollfd = epoll_create(NB_FD);
318 if (epollfd < 0) {
319 perror("[eppoll] create");
320 goto end;
321 }
322
323 epoll_event.events = EPOLLIN | EPOLLPRI | EPOLLET;
324 epoll_event.data.fd = wait_fd;
325 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, wait_fd, &epoll_event);
326 if (ret < 0) {
327 perror("[eppoll] add");
5305e823 328 goto error;
a0b1f42c
JD
329 }
330
331 if (timeout > 0) {
332 ret = epoll_pwait(epollfd, &epoll_event, 1, timeout, NULL);
333 } else {
334 ret = epoll_pwait(epollfd, &epoll_event, 1, -1, NULL);
335 }
336
337 if (ret == 1) {
338 printf("# [eppoll] data available\n");
339 ret = read(wait_fd, buf, BUF_SIZE);
340 if (ret < 0) {
341 perror("[eppoll] read");
342 }
343 } else if (ret == 0) {
344 printf("# [eppoll] timeout\n");
345 } else {
346 perror("epoll_pwait");
347 }
348
5305e823
FD
349error:
350 close(epollfd);
a0b1f42c
JD
351end:
352 return;
353}
354
f12eb9c1 355static
a0b1f42c
JD
356void run_working_cases(void)
357{
358 int ret;
359 int pipe_fds[2];
360
361 if (timeout > 0) {
362 /*
363 * We need an input pipe for some cases and stdin might
364 * have random data, so we create a dummy pipe for this
365 * test to make sure we are running under clean conditions.
366 */
367 ret = pipe(pipe_fds);
368 if (ret != 0) {
369 perror("pipe");
370 goto end;
371 }
372 wait_fd = pipe_fds[0];
373 }
374 test_select();
375 test_pselect();
376 test_select_big();
377 test_poll();
378 test_ppoll();
379 test_epoll();
380 test_pepoll();
381
382 if (timeout > 0) {
383 ret = close(pipe_fds[0]);
384 if (ret) {
385 perror("close");
386 }
387 ret = close(pipe_fds[1]);
388 if (ret) {
389 perror("close");
390 }
391 }
392
393end:
394 return;
395}
396
397/*
398 * Ask for 100 FDs in a buffer for allocated for only 1 FD, should
399 * segfault (eventually with a "*** stack smashing detected ***" message).
400 * The event should contain an array of 100 FDs filled with garbage.
401 */
f12eb9c1 402static
a0b1f42c
JD
403void ppoll_fds_buffer_overflow(void)
404{
405 struct pollfd ufds[NB_FD];
406 char buf[BUF_SIZE];
407 int ret;
408
409 ufds[0].fd = wait_fd;
410 ufds[0].events = POLLIN|POLLPRI;
411
412 ret = syscall(SYS_ppoll, ufds, 100, NULL, NULL);
413
414 if (ret < 0) {
415 perror("ppoll");
416 } else if (ret > 0) {
417 printf("# [ppoll] data available\n");
418 ret = read(wait_fd, buf, BUF_SIZE);
419 if (ret < 0) {
420 perror("[ppoll] read");
421 }
422 } else {
423 printf("# [ppoll] timeout\n");
424 }
425
426 return;
427}
428
429/*
430 * Ask for ULONG_MAX FDs in a buffer for allocated for only 1 FD, should
431 * cleanly fail with a "Invalid argument".
432 * The event should contain an empty array of FDs and overflow = 1.
433 */
f12eb9c1 434static
a0b1f42c
JD
435void ppoll_fds_ulong_max(void)
436{
437 struct pollfd ufds[NB_FD];
438 char buf[BUF_SIZE];
439 int ret;
440
441 ufds[0].fd = wait_fd;
442 ufds[0].events = POLLIN|POLLPRI;
443
444 ret = syscall(SYS_ppoll, ufds, ULONG_MAX, NULL, NULL);
445
446 if (ret < 0) {
447 perror("# ppoll");
448 } else if (ret > 0) {
449 printf("# [ppoll] data available\n");
450 ret = read(wait_fd, buf, BUF_SIZE);
451 if (ret < 0) {
452 perror("[ppoll] read");
453 }
454 } else {
455 printf("# [ppoll] timeout\n");
456 }
457
458 return;
459}
460
461/*
8b3b99e2
FD
462 * Pass an invalid file descriptor to pselect6(). The syscall should return
463 * -EBADF. The recorded event should contain a "ret = -EBADF (-9)".
a0b1f42c 464 */
f12eb9c1 465static
8b3b99e2 466void pselect_invalid_fd(void)
a0b1f42c 467{
8b3b99e2 468 fd_set rfds;
a0b1f42c 469 int ret;
8b3b99e2 470 int fd;
a0b1f42c
JD
471 char buf[BUF_SIZE];
472
473 /*
8b3b99e2 474 * Open a file, close it and use the closed FD in the pselect6 call.
a0b1f42c 475 */
8b3b99e2
FD
476
477 fd = open("/dev/null", O_RDONLY);
478 if (fd == -1) {
479 perror("open");
480 goto error;
481 }
482
483 ret = close(fd);
484 if (ret == -1) {
485 perror("close");
486 goto error;
a0b1f42c 487 }
e593ee02 488
8b3b99e2
FD
489 FD_ZERO(&rfds);
490 FD_SET(fd, &rfds);
a0b1f42c 491
8b3b99e2 492 ret = syscall(SYS_pselect6, fd + 1, &rfds, NULL, NULL, NULL, NULL);
a0b1f42c
JD
493 if (ret == -1) {
494 perror("# pselect()");
495 } else if (ret) {
496 printf("# [pselect] data available\n");
497 ret = read(wait_fd, buf, BUF_SIZE);
498 if (ret < 0) {
499 perror("[pselect] read");
500 }
501 } else {
502 printf("# [pselect] timeout\n");
503 }
8b3b99e2
FD
504error:
505 return;
a0b1f42c
JD
506}
507
508/*
509 * Invalid pointer as writefds, should output a ppoll event
510 * with 0 FDs.
511 */
f12eb9c1 512static
a0b1f42c
JD
513void pselect_invalid_pointer(void)
514{
515 fd_set rfds;
516 int ret;
517 char buf[BUF_SIZE];
518 void *invalid = (void *) 0x42;
519
520 FD_ZERO(&rfds);
521 FD_SET(wait_fd, &rfds);
522
523 ret = syscall(SYS_pselect6, 1, &rfds, (fd_set *) invalid, NULL, NULL,
524 NULL);
525
526 if (ret == -1) {
527 perror("# pselect()");
528 } else if (ret) {
529 printf("# [pselect] data available\n");
530 ret = read(wait_fd, buf, BUF_SIZE);
531 if (ret < 0) {
532 perror("[pselect] read");
533 }
534 } else {
535 printf("# [pselect] timeout\n");
536 }
537
538}
539
540/*
541 * Pass an invalid pointer to epoll_pwait, should fail with
542 * "Bad address", the event returns 0 FDs.
543 */
f12eb9c1 544static
a0b1f42c
JD
545void epoll_pwait_invalid_pointer(void)
546{
547 int ret, epollfd;
548 char buf[BUF_SIZE];
549 struct epoll_event epoll_event;
550 void *invalid = (void *) 0x42;
551
552 epollfd = epoll_create(NB_FD);
553 if (epollfd < 0) {
554 perror("[eppoll] create");
555 goto end;
556 }
557
558 epoll_event.events = EPOLLIN | EPOLLPRI | EPOLLET;
559 epoll_event.data.fd = wait_fd;
560 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, wait_fd, &epoll_event);
561 if (ret < 0) {
562 perror("[eppoll] add");
5305e823 563 goto error;
a0b1f42c
JD
564 }
565
566 ret = syscall(SYS_epoll_pwait, epollfd,
567 (struct epoll_event *) invalid, 1, -1, NULL);
568
569 if (ret == 1) {
570 printf("# [eppoll] data available\n");
571 ret = read(wait_fd, buf, BUF_SIZE);
572 if (ret < 0) {
573 perror("[eppoll] read");
574 }
575 } else if (ret == 0) {
576 printf("# [eppoll] timeout\n");
577 } else {
578 perror("# epoll_pwait");
579 }
580
5305e823
FD
581error:
582 close(epollfd);
a0b1f42c
JD
583end:
584 return;
585}
586
587/*
588 * Set maxevents to INT_MAX, should output "Invalid argument"
589 * The event should return an empty array.
590 */
f12eb9c1 591static
a0b1f42c
JD
592void epoll_pwait_int_max(void)
593{
594 int ret, epollfd;
595 char buf[BUF_SIZE];
596 struct epoll_event epoll_event;
597
598 epollfd = epoll_create(NB_FD);
599 if (epollfd < 0) {
600 perror("[eppoll] create");
601 goto end;
602 }
603
604 epoll_event.events = EPOLLIN | EPOLLPRI | EPOLLET;
605 epoll_event.data.fd = wait_fd;
606 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, wait_fd, &epoll_event);
607 if (ret < 0) {
608 perror("[eppoll] add");
5305e823 609 goto error;
a0b1f42c
JD
610 }
611
612 ret = syscall(SYS_epoll_pwait, epollfd, &epoll_event, INT_MAX, -1,
613 NULL);
614
615 if (ret == 1) {
616 printf("# [eppoll] data available\n");
617 ret = read(wait_fd, buf, BUF_SIZE);
618 if (ret < 0) {
619 perror("[eppoll] read");
620 }
621 } else if (ret == 0) {
622 printf("# [eppoll] timeout\n");
623 } else {
624 perror("# epoll_pwait");
625 }
626
5305e823
FD
627error:
628 close(epollfd);
a0b1f42c
JD
629end:
630 return;
631}
632
f12eb9c1 633static
a0b1f42c
JD
634void *ppoll_writer(void *arg)
635{
636 struct ppoll_thread_data *data = (struct ppoll_thread_data *) arg;
637
638 while (!stop_thread) {
639 memset(data->ufds, data->value,
640 MAX_FDS * sizeof(struct pollfd));
641 usleep(100);
642 }
643
644 return NULL;
645}
646
f12eb9c1 647static
a0b1f42c
JD
648void do_ppoll(int *fds, struct pollfd *ufds)
649{
650 int i, ret;
651 struct timespec ts;
652 char buf[BUF_SIZE];
653
654 ts.tv_sec = 0;
655 ts.tv_nsec = 1 * MSEC_PER_NSEC;
656
657 for (i = 0; i < MAX_FDS; i++) {
658 ufds[i].fd = fds[i];
659 ufds[i].events = POLLIN|POLLPRI;
660 }
661
662 ret = ppoll(ufds, MAX_FDS, &ts, NULL);
663
664 if (ret < 0) {
665 perror("ppoll");
666 } else if (ret > 0) {
667 printf("# [ppoll] data available\n");
668 ret = read(wait_fd, buf, BUF_SIZE);
669 if (ret < 0) {
670 perror("[ppoll] read");
671 }
672 } else {
673 printf("# [ppoll] timeout\n");
674 }
675}
676
f12eb9c1 677static
a0b1f42c
JD
678void stress_ppoll(int *fds, int value)
679{
680 pthread_t writer;
681 int iter, ret;
682 struct ppoll_thread_data thread_data;
683 struct pollfd ufds[MAX_FDS];
684
685 thread_data.ufds = ufds;
686 thread_data.value = value;
687
688 stop_thread = 0;
689 ret = pthread_create(&writer, NULL, &ppoll_writer, (void *) &thread_data);
690 if (ret != 0) {
691 fprintf(stderr, "[error] pthread_create\n");
692 goto end;
693 }
694 for (iter = 0; iter < NR_ITER; iter++) {
695 do_ppoll(fds, ufds);
696 }
697 stop_thread = 1;
9d558571
JG
698 ret = pthread_join(writer, NULL);
699 if (ret) {
700 fprintf(stderr, "[error] pthread_join\n");
701 goto end;
702 }
a0b1f42c
JD
703end:
704 return;
705}
706
707/*
708 * 3 rounds of NR_ITER iterations with concurrent updates of the pollfd
709 * structure:
710 * - memset to 0
711 * - memset to 1
712 * - memset to INT_MAX
713 * Waits for input, but also set a timeout in case the input FD is overwritten
714 * before entering in the syscall. We use MAX_FDS FDs (dup of stdin), so the
715 * resulting trace is big (20MB).
716 *
717 * ppoll should work as expected and the trace should be readable at the end.
718 */
f12eb9c1 719static
a0b1f42c
JD
720void ppoll_concurrent_write(void)
721{
722 int i, ret, fds[MAX_FDS];
723
724 for (i = 0; i < MAX_FDS; i++) {
725 fds[i] = dup(wait_fd);
726 if (fds[i] < 0) {
727 perror("dup");
728 }
729 }
730
731 stress_ppoll(fds, 0);
732 stress_ppoll(fds, 1);
733 stress_ppoll(fds, INT_MAX);
734
735 for (i = 0; i < MAX_FDS; i++) {
736 ret = close(fds[i]);
737 if (ret != 0) {
738 perror("close");
739 }
740 }
741
742 return;
743}
744
f12eb9c1 745static
a0b1f42c
JD
746void *epoll_pwait_writer(void *addr)
747{
748 srand(time(NULL));
749
750 while (!stop_thread) {
751 usleep(rand() % 30);
752 munmap(addr, MAX_FDS * sizeof(struct epoll_event));
753 }
754
755 return NULL;
756}
757
758/*
759 * epoll_pwait on MAX_FDS fds while a concurrent thread munmaps the
760 * buffer allocated for the returned data. This should randomly segfault.
761 * The trace should be readable and no kernel OOPS should occur.
762 */
f12eb9c1 763static
a0b1f42c
JD
764void epoll_pwait_concurrent_munmap(void)
765{
766 int ret, epollfd, i, fds[MAX_FDS];
767 char buf[BUF_SIZE];
768 struct epoll_event *epoll_event;
a0b1f42c
JD
769 pthread_t writer;
770
7f6288c8
JG
771 for (i = 0; i < MAX_FDS; i++) {
772 fds[i] = -1;
773 }
a0b1f42c
JD
774 epollfd = epoll_create(MAX_FDS);
775 if (epollfd < 0) {
776 perror("[eppoll] create");
777 goto end;
778 }
779
36bc42d9 780 epoll_event = mmap(NULL, MAX_FDS * sizeof(struct epoll_event),
a0b1f42c
JD
781 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
782 -1, 0);
783 if (epoll_event == MAP_FAILED) {
784 perror("mmap");
5305e823 785 goto error;
a0b1f42c
JD
786 }
787
788 for (i = 0; i < MAX_FDS; i++) {
789 fds[i] = dup(wait_fd);
790 if (fds[i] < 0) {
791 perror("dup");
792 }
793 epoll_event[i].events = EPOLLIN | EPOLLPRI | EPOLLET;
794 epoll_event[i].data.fd = fds[i];
795 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], epoll_event);
796 if (ret < 0) {
797 perror("[eppoll] add");
5305e823 798 goto error_unmap;
a0b1f42c
JD
799 }
800 }
801 stop_thread = 0;
d542c0ae
JG
802 ret = pthread_create(&writer, NULL, &epoll_pwait_writer,
803 (void *) epoll_event);
804 if (ret != 0) {
805 fprintf(stderr, "[error] pthread_create\n");
5305e823 806 goto error_unmap;
d542c0ae 807 }
a0b1f42c
JD
808
809 ret = epoll_pwait(epollfd, epoll_event, 1, 1, NULL);
810
811 if (ret == 1) {
812 printf("# [eppoll] data available\n");
813 ret = read(wait_fd, buf, BUF_SIZE);
814 if (ret < 0) {
815 perror("[eppoll] read");
816 }
817 } else if (ret == 0) {
818 printf("# [eppoll] timeout\n");
819 } else {
820 perror("# epoll_pwait");
821 }
822
823 stop_thread = 1;
9d558571
JG
824 ret = pthread_join(writer, NULL);
825 if (ret) {
826 fprintf(stderr, "[error] pthread_join\n");
5305e823 827 goto error_unmap;
9d558571 828 }
5305e823 829error_unmap:
a0b1f42c
JD
830 for (i = 0; i < MAX_FDS; i++) {
831 ret = close(fds[i]);
832 if (ret != 0) {
833 perror("close");
834 }
835 }
836
36bc42d9 837 ret = munmap(epoll_event, MAX_FDS * sizeof(struct epoll_event));
a0b1f42c
JD
838 if (ret != 0) {
839 perror("munmap");
840 }
841
5305e823
FD
842error:
843 close(epollfd);
a0b1f42c
JD
844end:
845 return;
846}
847
f12eb9c1 848static
a0b1f42c
JD
849void print_list(void)
850{
851 fprintf(stderr, "Test list (-t X):\n");
852 fprintf(stderr, "\t1: Working cases for select, pselect6, poll, ppoll "
853 "and epoll, waiting for input\n");
854 fprintf(stderr, "\t2: Timeout cases (1ms) for select, pselect6, poll, "
855 "ppoll and epoll\n");
8b3b99e2 856 fprintf(stderr, "\t3: pselect with an invalid fd\n");
a0b1f42c
JD
857 fprintf(stderr, "\t4: ppoll with %d FDs\n", MAX_FDS);
858 fprintf(stderr, "\t5: ppoll buffer overflow, should segfault, waits "
859 "for input\n");
8b3b99e2 860 fprintf(stderr, "\t6: pselect with an invalid pointer, waits for "
a0b1f42c
JD
861 "input\n");
862 fprintf(stderr, "\t7: ppoll with ulong_max fds, waits for input\n");
8b3b99e2 863 fprintf(stderr, "\t8: epoll_pwait with an invalid pointer, waits for "
a0b1f42c
JD
864 "input\n");
865 fprintf(stderr, "\t9: epoll_pwait with maxevents set to INT_MAX, "
866 "waits for input\n");
867 fprintf(stderr, "\t10: ppoll with concurrent updates of the structure "
868 "from user-space, stress test (3000 iterations), "
869 "waits for input + timeout 1ms\n");
870 fprintf(stderr, "\t11: epoll_pwait with concurrent munmap of the buffer "
871 "from user-space, should randomly segfault, run "
872 "multiple times, waits for input + timeout 1ms\n");
873}
874
875int main(int argc, const char **argv)
876{
877 int c, ret, test = -1;
878 poptContext optCon;
879 struct rlimit open_lim;
880
881 struct poptOption optionsTable[] = {
882 { "test", 't', POPT_ARG_INT, &test, 0,
883 "Test to run", NULL },
884 { "list", 'l', 0, 0, 'l',
885 "List of tests (-t X)", NULL },
886 POPT_AUTOHELP
887 { NULL, 0, 0, NULL, 0 }
888 };
889
890 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
891
892 if (argc < 2) {
893 poptPrintUsage(optCon, stderr, 0);
894 ret = -1;
895 goto end;
896 }
897
898 ret = 0;
899
900 while ((c = poptGetNextOpt(optCon)) >= 0) {
901 switch(c) {
902 case 'l':
903 print_list();
904 goto end;
905 }
906 }
907
908 open_lim.rlim_cur = MAX_FDS + MIN_NR_FDS;
909 open_lim.rlim_max = MAX_FDS + MIN_NR_FDS;
910
911 ret = setrlimit(RLIMIT_NOFILE, &open_lim);
912 if (ret < 0) {
913 perror("setrlimit");
914 goto end;
915 }
916
917 /*
918 * Some tests might segfault, but we need the getpid() to be output
919 * for the validation, disabling the buffering on stdout works.
920 */
921 setbuf(stdout, NULL);
922 printf("%d\n", getpid());
923
924 wait_fd = STDIN_FILENO;
925
926 switch(test) {
927 case 1:
928 timeout = -1;
929 run_working_cases();
930 break;
931 case 2:
932 timeout = 1;
933 run_working_cases();
934 break;
935 case 3:
8b3b99e2 936 pselect_invalid_fd();
a0b1f42c
JD
937 break;
938 case 4:
939 test_ppoll_big();
940 break;
941 case 5:
942 ppoll_fds_buffer_overflow();
943 break;
944 case 6:
945 pselect_invalid_pointer();
946 break;
947 case 7:
948 ppoll_fds_ulong_max();
949 break;
950 case 8:
951 epoll_pwait_invalid_pointer();
952 break;
953 case 9:
954 epoll_pwait_int_max();
955 break;
956 case 10:
957 ppoll_concurrent_write();
958 break;
959 case 11:
960 epoll_pwait_concurrent_munmap();
961 break;
962 default:
963 poptPrintUsage(optCon, stderr, 0);
964 ret = -1;
965 break;
966 }
967
968end:
969 poptFreeContext(optCon);
970 return ret;
971}
This page took 0.0732 seconds and 4 git commands to generate.