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