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