Fix all -Wmissing-declarations warning instances
[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");
283 goto end;
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
304end:
305 return;
306}
307
f12eb9c1 308static
a0b1f42c
JD
309void test_pepoll(void)
310{
311 int ret, epollfd;
312 char buf[BUF_SIZE];
313 struct epoll_event epoll_event;
314
315 epollfd = epoll_create(NB_FD);
316 if (epollfd < 0) {
317 perror("[eppoll] create");
318 goto end;
319 }
320
321 epoll_event.events = EPOLLIN | EPOLLPRI | EPOLLET;
322 epoll_event.data.fd = wait_fd;
323 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, wait_fd, &epoll_event);
324 if (ret < 0) {
325 perror("[eppoll] add");
326 goto end;
327 }
328
329 if (timeout > 0) {
330 ret = epoll_pwait(epollfd, &epoll_event, 1, timeout, NULL);
331 } else {
332 ret = epoll_pwait(epollfd, &epoll_event, 1, -1, NULL);
333 }
334
335 if (ret == 1) {
336 printf("# [eppoll] data available\n");
337 ret = read(wait_fd, buf, BUF_SIZE);
338 if (ret < 0) {
339 perror("[eppoll] read");
340 }
341 } else if (ret == 0) {
342 printf("# [eppoll] timeout\n");
343 } else {
344 perror("epoll_pwait");
345 }
346
347end:
348 return;
349}
350
f12eb9c1 351static
a0b1f42c
JD
352void run_working_cases(void)
353{
354 int ret;
355 int pipe_fds[2];
356
357 if (timeout > 0) {
358 /*
359 * We need an input pipe for some cases and stdin might
360 * have random data, so we create a dummy pipe for this
361 * test to make sure we are running under clean conditions.
362 */
363 ret = pipe(pipe_fds);
364 if (ret != 0) {
365 perror("pipe");
366 goto end;
367 }
368 wait_fd = pipe_fds[0];
369 }
370 test_select();
371 test_pselect();
372 test_select_big();
373 test_poll();
374 test_ppoll();
375 test_epoll();
376 test_pepoll();
377
378 if (timeout > 0) {
379 ret = close(pipe_fds[0]);
380 if (ret) {
381 perror("close");
382 }
383 ret = close(pipe_fds[1]);
384 if (ret) {
385 perror("close");
386 }
387 }
388
389end:
390 return;
391}
392
393/*
394 * Ask for 100 FDs in a buffer for allocated for only 1 FD, should
395 * segfault (eventually with a "*** stack smashing detected ***" message).
396 * The event should contain an array of 100 FDs filled with garbage.
397 */
f12eb9c1 398static
a0b1f42c
JD
399void ppoll_fds_buffer_overflow(void)
400{
401 struct pollfd ufds[NB_FD];
402 char buf[BUF_SIZE];
403 int ret;
404
405 ufds[0].fd = wait_fd;
406 ufds[0].events = POLLIN|POLLPRI;
407
408 ret = syscall(SYS_ppoll, ufds, 100, NULL, NULL);
409
410 if (ret < 0) {
411 perror("ppoll");
412 } else if (ret > 0) {
413 printf("# [ppoll] data available\n");
414 ret = read(wait_fd, buf, BUF_SIZE);
415 if (ret < 0) {
416 perror("[ppoll] read");
417 }
418 } else {
419 printf("# [ppoll] timeout\n");
420 }
421
422 return;
423}
424
425/*
426 * Ask for ULONG_MAX FDs in a buffer for allocated for only 1 FD, should
427 * cleanly fail with a "Invalid argument".
428 * The event should contain an empty array of FDs and overflow = 1.
429 */
f12eb9c1 430static
a0b1f42c
JD
431void ppoll_fds_ulong_max(void)
432{
433 struct pollfd ufds[NB_FD];
434 char buf[BUF_SIZE];
435 int ret;
436
437 ufds[0].fd = wait_fd;
438 ufds[0].events = POLLIN|POLLPRI;
439
440 ret = syscall(SYS_ppoll, ufds, ULONG_MAX, NULL, NULL);
441
442 if (ret < 0) {
443 perror("# ppoll");
444 } else if (ret > 0) {
445 printf("# [ppoll] data available\n");
446 ret = read(wait_fd, buf, BUF_SIZE);
447 if (ret < 0) {
448 perror("[ppoll] read");
449 }
450 } else {
451 printf("# [ppoll] timeout\n");
452 }
453
454 return;
455}
456
457/*
8b3b99e2
FD
458 * Pass an invalid file descriptor to pselect6(). The syscall should return
459 * -EBADF. The recorded event should contain a "ret = -EBADF (-9)".
a0b1f42c 460 */
f12eb9c1 461static
8b3b99e2 462void pselect_invalid_fd(void)
a0b1f42c 463{
8b3b99e2 464 fd_set rfds;
a0b1f42c 465 int ret;
8b3b99e2 466 int fd;
a0b1f42c
JD
467 char buf[BUF_SIZE];
468
469 /*
8b3b99e2 470 * Open a file, close it and use the closed FD in the pselect6 call.
a0b1f42c 471 */
8b3b99e2
FD
472
473 fd = open("/dev/null", O_RDONLY);
474 if (fd == -1) {
475 perror("open");
476 goto error;
477 }
478
479 ret = close(fd);
480 if (ret == -1) {
481 perror("close");
482 goto error;
a0b1f42c 483 }
e593ee02 484
8b3b99e2
FD
485 FD_ZERO(&rfds);
486 FD_SET(fd, &rfds);
a0b1f42c 487
8b3b99e2 488 ret = syscall(SYS_pselect6, fd + 1, &rfds, NULL, NULL, NULL, NULL);
a0b1f42c
JD
489 if (ret == -1) {
490 perror("# pselect()");
491 } else if (ret) {
492 printf("# [pselect] data available\n");
493 ret = read(wait_fd, buf, BUF_SIZE);
494 if (ret < 0) {
495 perror("[pselect] read");
496 }
497 } else {
498 printf("# [pselect] timeout\n");
499 }
8b3b99e2
FD
500error:
501 return;
a0b1f42c
JD
502}
503
504/*
505 * Invalid pointer as writefds, should output a ppoll event
506 * with 0 FDs.
507 */
f12eb9c1 508static
a0b1f42c
JD
509void pselect_invalid_pointer(void)
510{
511 fd_set rfds;
512 int ret;
513 char buf[BUF_SIZE];
514 void *invalid = (void *) 0x42;
515
516 FD_ZERO(&rfds);
517 FD_SET(wait_fd, &rfds);
518
519 ret = syscall(SYS_pselect6, 1, &rfds, (fd_set *) invalid, NULL, NULL,
520 NULL);
521
522 if (ret == -1) {
523 perror("# pselect()");
524 } else if (ret) {
525 printf("# [pselect] data available\n");
526 ret = read(wait_fd, buf, BUF_SIZE);
527 if (ret < 0) {
528 perror("[pselect] read");
529 }
530 } else {
531 printf("# [pselect] timeout\n");
532 }
533
534}
535
536/*
537 * Pass an invalid pointer to epoll_pwait, should fail with
538 * "Bad address", the event returns 0 FDs.
539 */
f12eb9c1 540static
a0b1f42c
JD
541void epoll_pwait_invalid_pointer(void)
542{
543 int ret, epollfd;
544 char buf[BUF_SIZE];
545 struct epoll_event epoll_event;
546 void *invalid = (void *) 0x42;
547
548 epollfd = epoll_create(NB_FD);
549 if (epollfd < 0) {
550 perror("[eppoll] create");
551 goto end;
552 }
553
554 epoll_event.events = EPOLLIN | EPOLLPRI | EPOLLET;
555 epoll_event.data.fd = wait_fd;
556 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, wait_fd, &epoll_event);
557 if (ret < 0) {
558 perror("[eppoll] add");
559 goto end;
560 }
561
562 ret = syscall(SYS_epoll_pwait, epollfd,
563 (struct epoll_event *) invalid, 1, -1, NULL);
564
565 if (ret == 1) {
566 printf("# [eppoll] data available\n");
567 ret = read(wait_fd, buf, BUF_SIZE);
568 if (ret < 0) {
569 perror("[eppoll] read");
570 }
571 } else if (ret == 0) {
572 printf("# [eppoll] timeout\n");
573 } else {
574 perror("# epoll_pwait");
575 }
576
577end:
578 return;
579}
580
581/*
582 * Set maxevents to INT_MAX, should output "Invalid argument"
583 * The event should return an empty array.
584 */
f12eb9c1 585static
a0b1f42c
JD
586void epoll_pwait_int_max(void)
587{
588 int ret, epollfd;
589 char buf[BUF_SIZE];
590 struct epoll_event epoll_event;
591
592 epollfd = epoll_create(NB_FD);
593 if (epollfd < 0) {
594 perror("[eppoll] create");
595 goto end;
596 }
597
598 epoll_event.events = EPOLLIN | EPOLLPRI | EPOLLET;
599 epoll_event.data.fd = wait_fd;
600 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, wait_fd, &epoll_event);
601 if (ret < 0) {
602 perror("[eppoll] add");
603 goto end;
604 }
605
606 ret = syscall(SYS_epoll_pwait, epollfd, &epoll_event, INT_MAX, -1,
607 NULL);
608
609 if (ret == 1) {
610 printf("# [eppoll] data available\n");
611 ret = read(wait_fd, buf, BUF_SIZE);
612 if (ret < 0) {
613 perror("[eppoll] read");
614 }
615 } else if (ret == 0) {
616 printf("# [eppoll] timeout\n");
617 } else {
618 perror("# epoll_pwait");
619 }
620
621end:
622 return;
623}
624
f12eb9c1 625static
a0b1f42c
JD
626void *ppoll_writer(void *arg)
627{
628 struct ppoll_thread_data *data = (struct ppoll_thread_data *) arg;
629
630 while (!stop_thread) {
631 memset(data->ufds, data->value,
632 MAX_FDS * sizeof(struct pollfd));
633 usleep(100);
634 }
635
636 return NULL;
637}
638
f12eb9c1 639static
a0b1f42c
JD
640void do_ppoll(int *fds, struct pollfd *ufds)
641{
642 int i, ret;
643 struct timespec ts;
644 char buf[BUF_SIZE];
645
646 ts.tv_sec = 0;
647 ts.tv_nsec = 1 * MSEC_PER_NSEC;
648
649 for (i = 0; i < MAX_FDS; i++) {
650 ufds[i].fd = fds[i];
651 ufds[i].events = POLLIN|POLLPRI;
652 }
653
654 ret = ppoll(ufds, MAX_FDS, &ts, NULL);
655
656 if (ret < 0) {
657 perror("ppoll");
658 } else if (ret > 0) {
659 printf("# [ppoll] data available\n");
660 ret = read(wait_fd, buf, BUF_SIZE);
661 if (ret < 0) {
662 perror("[ppoll] read");
663 }
664 } else {
665 printf("# [ppoll] timeout\n");
666 }
667}
668
f12eb9c1 669static
a0b1f42c
JD
670void stress_ppoll(int *fds, int value)
671{
672 pthread_t writer;
673 int iter, ret;
674 struct ppoll_thread_data thread_data;
675 struct pollfd ufds[MAX_FDS];
676
677 thread_data.ufds = ufds;
678 thread_data.value = value;
679
680 stop_thread = 0;
681 ret = pthread_create(&writer, NULL, &ppoll_writer, (void *) &thread_data);
682 if (ret != 0) {
683 fprintf(stderr, "[error] pthread_create\n");
684 goto end;
685 }
686 for (iter = 0; iter < NR_ITER; iter++) {
687 do_ppoll(fds, ufds);
688 }
689 stop_thread = 1;
9d558571
JG
690 ret = pthread_join(writer, NULL);
691 if (ret) {
692 fprintf(stderr, "[error] pthread_join\n");
693 goto end;
694 }
a0b1f42c
JD
695end:
696 return;
697}
698
699/*
700 * 3 rounds of NR_ITER iterations with concurrent updates of the pollfd
701 * structure:
702 * - memset to 0
703 * - memset to 1
704 * - memset to INT_MAX
705 * Waits for input, but also set a timeout in case the input FD is overwritten
706 * before entering in the syscall. We use MAX_FDS FDs (dup of stdin), so the
707 * resulting trace is big (20MB).
708 *
709 * ppoll should work as expected and the trace should be readable at the end.
710 */
f12eb9c1 711static
a0b1f42c
JD
712void ppoll_concurrent_write(void)
713{
714 int i, ret, fds[MAX_FDS];
715
716 for (i = 0; i < MAX_FDS; i++) {
717 fds[i] = dup(wait_fd);
718 if (fds[i] < 0) {
719 perror("dup");
720 }
721 }
722
723 stress_ppoll(fds, 0);
724 stress_ppoll(fds, 1);
725 stress_ppoll(fds, INT_MAX);
726
727 for (i = 0; i < MAX_FDS; i++) {
728 ret = close(fds[i]);
729 if (ret != 0) {
730 perror("close");
731 }
732 }
733
734 return;
735}
736
f12eb9c1 737static
a0b1f42c
JD
738void *epoll_pwait_writer(void *addr)
739{
740 srand(time(NULL));
741
742 while (!stop_thread) {
743 usleep(rand() % 30);
744 munmap(addr, MAX_FDS * sizeof(struct epoll_event));
745 }
746
747 return NULL;
748}
749
750/*
751 * epoll_pwait on MAX_FDS fds while a concurrent thread munmaps the
752 * buffer allocated for the returned data. This should randomly segfault.
753 * The trace should be readable and no kernel OOPS should occur.
754 */
f12eb9c1 755static
a0b1f42c
JD
756void epoll_pwait_concurrent_munmap(void)
757{
758 int ret, epollfd, i, fds[MAX_FDS];
759 char buf[BUF_SIZE];
760 struct epoll_event *epoll_event;
a0b1f42c
JD
761 pthread_t writer;
762
7f6288c8
JG
763 for (i = 0; i < MAX_FDS; i++) {
764 fds[i] = -1;
765 }
a0b1f42c
JD
766 epollfd = epoll_create(MAX_FDS);
767 if (epollfd < 0) {
768 perror("[eppoll] create");
769 goto end;
770 }
771
36bc42d9 772 epoll_event = mmap(NULL, MAX_FDS * sizeof(struct epoll_event),
a0b1f42c
JD
773 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
774 -1, 0);
775 if (epoll_event == MAP_FAILED) {
776 perror("mmap");
777 goto end;
778 }
779
780 for (i = 0; i < MAX_FDS; i++) {
781 fds[i] = dup(wait_fd);
782 if (fds[i] < 0) {
783 perror("dup");
784 }
785 epoll_event[i].events = EPOLLIN | EPOLLPRI | EPOLLET;
786 epoll_event[i].data.fd = fds[i];
787 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], epoll_event);
788 if (ret < 0) {
789 perror("[eppoll] add");
790 goto end_unmap;
791 }
792 }
793 stop_thread = 0;
d542c0ae
JG
794 ret = pthread_create(&writer, NULL, &epoll_pwait_writer,
795 (void *) epoll_event);
796 if (ret != 0) {
797 fprintf(stderr, "[error] pthread_create\n");
29623dbc 798 goto end_unmap;
d542c0ae 799 }
a0b1f42c
JD
800
801 ret = epoll_pwait(epollfd, epoll_event, 1, 1, NULL);
802
803 if (ret == 1) {
804 printf("# [eppoll] data available\n");
805 ret = read(wait_fd, buf, BUF_SIZE);
806 if (ret < 0) {
807 perror("[eppoll] read");
808 }
809 } else if (ret == 0) {
810 printf("# [eppoll] timeout\n");
811 } else {
812 perror("# epoll_pwait");
813 }
814
815 stop_thread = 1;
9d558571
JG
816 ret = pthread_join(writer, NULL);
817 if (ret) {
818 fprintf(stderr, "[error] pthread_join\n");
819 goto end_unmap;
820 }
a0b1f42c
JD
821end_unmap:
822 for (i = 0; i < MAX_FDS; i++) {
823 ret = close(fds[i]);
824 if (ret != 0) {
825 perror("close");
826 }
827 }
828
36bc42d9 829 ret = munmap(epoll_event, MAX_FDS * sizeof(struct epoll_event));
a0b1f42c
JD
830 if (ret != 0) {
831 perror("munmap");
832 }
833
834end:
835 return;
836}
837
f12eb9c1 838static
a0b1f42c
JD
839void print_list(void)
840{
841 fprintf(stderr, "Test list (-t X):\n");
842 fprintf(stderr, "\t1: Working cases for select, pselect6, poll, ppoll "
843 "and epoll, waiting for input\n");
844 fprintf(stderr, "\t2: Timeout cases (1ms) for select, pselect6, poll, "
845 "ppoll and epoll\n");
8b3b99e2 846 fprintf(stderr, "\t3: pselect with an invalid fd\n");
a0b1f42c
JD
847 fprintf(stderr, "\t4: ppoll with %d FDs\n", MAX_FDS);
848 fprintf(stderr, "\t5: ppoll buffer overflow, should segfault, waits "
849 "for input\n");
8b3b99e2 850 fprintf(stderr, "\t6: pselect with an invalid pointer, waits for "
a0b1f42c
JD
851 "input\n");
852 fprintf(stderr, "\t7: ppoll with ulong_max fds, waits for input\n");
8b3b99e2 853 fprintf(stderr, "\t8: epoll_pwait with an invalid pointer, waits for "
a0b1f42c
JD
854 "input\n");
855 fprintf(stderr, "\t9: epoll_pwait with maxevents set to INT_MAX, "
856 "waits for input\n");
857 fprintf(stderr, "\t10: ppoll with concurrent updates of the structure "
858 "from user-space, stress test (3000 iterations), "
859 "waits for input + timeout 1ms\n");
860 fprintf(stderr, "\t11: epoll_pwait with concurrent munmap of the buffer "
861 "from user-space, should randomly segfault, run "
862 "multiple times, waits for input + timeout 1ms\n");
863}
864
865int main(int argc, const char **argv)
866{
867 int c, ret, test = -1;
868 poptContext optCon;
869 struct rlimit open_lim;
870
871 struct poptOption optionsTable[] = {
872 { "test", 't', POPT_ARG_INT, &test, 0,
873 "Test to run", NULL },
874 { "list", 'l', 0, 0, 'l',
875 "List of tests (-t X)", NULL },
876 POPT_AUTOHELP
877 { NULL, 0, 0, NULL, 0 }
878 };
879
880 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
881
882 if (argc < 2) {
883 poptPrintUsage(optCon, stderr, 0);
884 ret = -1;
885 goto end;
886 }
887
888 ret = 0;
889
890 while ((c = poptGetNextOpt(optCon)) >= 0) {
891 switch(c) {
892 case 'l':
893 print_list();
894 goto end;
895 }
896 }
897
898 open_lim.rlim_cur = MAX_FDS + MIN_NR_FDS;
899 open_lim.rlim_max = MAX_FDS + MIN_NR_FDS;
900
901 ret = setrlimit(RLIMIT_NOFILE, &open_lim);
902 if (ret < 0) {
903 perror("setrlimit");
904 goto end;
905 }
906
907 /*
908 * Some tests might segfault, but we need the getpid() to be output
909 * for the validation, disabling the buffering on stdout works.
910 */
911 setbuf(stdout, NULL);
912 printf("%d\n", getpid());
913
914 wait_fd = STDIN_FILENO;
915
916 switch(test) {
917 case 1:
918 timeout = -1;
919 run_working_cases();
920 break;
921 case 2:
922 timeout = 1;
923 run_working_cases();
924 break;
925 case 3:
8b3b99e2 926 pselect_invalid_fd();
a0b1f42c
JD
927 break;
928 case 4:
929 test_ppoll_big();
930 break;
931 case 5:
932 ppoll_fds_buffer_overflow();
933 break;
934 case 6:
935 pselect_invalid_pointer();
936 break;
937 case 7:
938 ppoll_fds_ulong_max();
939 break;
940 case 8:
941 epoll_pwait_invalid_pointer();
942 break;
943 case 9:
944 epoll_pwait_int_max();
945 break;
946 case 10:
947 ppoll_concurrent_write();
948 break;
949 case 11:
950 epoll_pwait_concurrent_munmap();
951 break;
952 default:
953 poptPrintUsage(optCon, stderr, 0);
954 ret = -1;
955 break;
956 }
957
958end:
959 poptFreeContext(optCon);
960 return ret;
961}
This page took 0.066874 seconds and 4 git commands to generate.