Test for select, poll and epoll syscall overrides
[lttng-tools.git] / tests / regression / kernel / select_poll_epoll.c
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>
20 #include <time.h>
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
33 static int timeout; /* seconds, -1 to disable */
34 volatile static int stop_thread;
35 static int wait_fd;
36
37 struct ppoll_thread_data {
38 struct pollfd *ufds;
39 int value;
40 };
41
42 void 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
87 end:
88 return;
89 }
90
91 void 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
124 void 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
157 void 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
181 void 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
213 void 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
252 void 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
290 end:
291 return;
292 }
293
294 void 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
332 end:
333 return;
334 }
335
336 void 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
373 end:
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 */
382 void 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 */
413 void 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 /*
440 * Select is limited to 1024 FDs, should output a pselect event
441 * with 0 FDs.
442 */
443 void pselect_fd_too_big(void)
444 {
445 fd_set rfds;
446 int ret;
447 int fd2;
448 char buf[BUF_SIZE];
449
450 /*
451 * Test if nfds > 1024.
452 * Make sure ulimit is set correctly (ulimit -n 2048).
453 */
454 fd2 = dup2(wait_fd, 2047);
455 if (fd2 != 2047) {
456 perror("dup2");
457 return;
458 }
459 FD_ZERO(&rfds);
460 FD_SET(fd2, &rfds);
461
462 ret = syscall(SYS_pselect6, fd2 + 1, &rfds, NULL, NULL, NULL, NULL);
463
464 if (ret == -1) {
465 perror("# pselect()");
466 } else if (ret) {
467 printf("# [pselect] data available\n");
468 ret = read(wait_fd, buf, BUF_SIZE);
469 if (ret < 0) {
470 perror("[pselect] read");
471 }
472 } else {
473 printf("# [pselect] timeout\n");
474 }
475
476 }
477
478 /*
479 * Invalid pointer as writefds, should output a ppoll event
480 * with 0 FDs.
481 */
482 void pselect_invalid_pointer(void)
483 {
484 fd_set rfds;
485 int ret;
486 char buf[BUF_SIZE];
487 void *invalid = (void *) 0x42;
488
489 FD_ZERO(&rfds);
490 FD_SET(wait_fd, &rfds);
491
492 ret = syscall(SYS_pselect6, 1, &rfds, (fd_set *) invalid, NULL, NULL,
493 NULL);
494
495 if (ret == -1) {
496 perror("# pselect()");
497 } else if (ret) {
498 printf("# [pselect] data available\n");
499 ret = read(wait_fd, buf, BUF_SIZE);
500 if (ret < 0) {
501 perror("[pselect] read");
502 }
503 } else {
504 printf("# [pselect] timeout\n");
505 }
506
507 }
508
509 /*
510 * Pass an invalid pointer to epoll_pwait, should fail with
511 * "Bad address", the event returns 0 FDs.
512 */
513 void epoll_pwait_invalid_pointer(void)
514 {
515 int ret, epollfd;
516 char buf[BUF_SIZE];
517 struct epoll_event epoll_event;
518 void *invalid = (void *) 0x42;
519
520 epollfd = epoll_create(NB_FD);
521 if (epollfd < 0) {
522 perror("[eppoll] create");
523 goto end;
524 }
525
526 epoll_event.events = EPOLLIN | EPOLLPRI | EPOLLET;
527 epoll_event.data.fd = wait_fd;
528 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, wait_fd, &epoll_event);
529 if (ret < 0) {
530 perror("[eppoll] add");
531 goto end;
532 }
533
534 ret = syscall(SYS_epoll_pwait, epollfd,
535 (struct epoll_event *) invalid, 1, -1, NULL);
536
537 if (ret == 1) {
538 printf("# [eppoll] data available\n");
539 ret = read(wait_fd, buf, BUF_SIZE);
540 if (ret < 0) {
541 perror("[eppoll] read");
542 }
543 } else if (ret == 0) {
544 printf("# [eppoll] timeout\n");
545 } else {
546 perror("# epoll_pwait");
547 }
548
549 end:
550 return;
551 }
552
553 /*
554 * Set maxevents to INT_MAX, should output "Invalid argument"
555 * The event should return an empty array.
556 */
557 void epoll_pwait_int_max(void)
558 {
559 int ret, epollfd;
560 char buf[BUF_SIZE];
561 struct epoll_event epoll_event;
562
563 epollfd = epoll_create(NB_FD);
564 if (epollfd < 0) {
565 perror("[eppoll] create");
566 goto end;
567 }
568
569 epoll_event.events = EPOLLIN | EPOLLPRI | EPOLLET;
570 epoll_event.data.fd = wait_fd;
571 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, wait_fd, &epoll_event);
572 if (ret < 0) {
573 perror("[eppoll] add");
574 goto end;
575 }
576
577 ret = syscall(SYS_epoll_pwait, epollfd, &epoll_event, INT_MAX, -1,
578 NULL);
579
580 if (ret == 1) {
581 printf("# [eppoll] data available\n");
582 ret = read(wait_fd, buf, BUF_SIZE);
583 if (ret < 0) {
584 perror("[eppoll] read");
585 }
586 } else if (ret == 0) {
587 printf("# [eppoll] timeout\n");
588 } else {
589 perror("# epoll_pwait");
590 }
591
592 end:
593 return;
594 }
595
596 void *ppoll_writer(void *arg)
597 {
598 struct ppoll_thread_data *data = (struct ppoll_thread_data *) arg;
599
600 while (!stop_thread) {
601 memset(data->ufds, data->value,
602 MAX_FDS * sizeof(struct pollfd));
603 usleep(100);
604 }
605
606 return NULL;
607 }
608
609 void do_ppoll(int *fds, struct pollfd *ufds)
610 {
611 int i, ret;
612 struct timespec ts;
613 char buf[BUF_SIZE];
614
615 ts.tv_sec = 0;
616 ts.tv_nsec = 1 * MSEC_PER_NSEC;
617
618 for (i = 0; i < MAX_FDS; i++) {
619 ufds[i].fd = fds[i];
620 ufds[i].events = POLLIN|POLLPRI;
621 }
622
623 ret = ppoll(ufds, MAX_FDS, &ts, NULL);
624
625 if (ret < 0) {
626 perror("ppoll");
627 } else if (ret > 0) {
628 printf("# [ppoll] data available\n");
629 ret = read(wait_fd, buf, BUF_SIZE);
630 if (ret < 0) {
631 perror("[ppoll] read");
632 }
633 } else {
634 printf("# [ppoll] timeout\n");
635 }
636 }
637
638 void stress_ppoll(int *fds, int value)
639 {
640 pthread_t writer;
641 int iter, ret;
642 struct ppoll_thread_data thread_data;
643 struct pollfd ufds[MAX_FDS];
644
645 thread_data.ufds = ufds;
646 thread_data.value = value;
647
648 stop_thread = 0;
649 ret = pthread_create(&writer, NULL, &ppoll_writer, (void *) &thread_data);
650 if (ret != 0) {
651 fprintf(stderr, "[error] pthread_create\n");
652 goto end;
653 }
654 for (iter = 0; iter < NR_ITER; iter++) {
655 do_ppoll(fds, ufds);
656 }
657 stop_thread = 1;
658 pthread_join(writer, NULL);
659 end:
660 return;
661 }
662
663 /*
664 * 3 rounds of NR_ITER iterations with concurrent updates of the pollfd
665 * structure:
666 * - memset to 0
667 * - memset to 1
668 * - memset to INT_MAX
669 * Waits for input, but also set a timeout in case the input FD is overwritten
670 * before entering in the syscall. We use MAX_FDS FDs (dup of stdin), so the
671 * resulting trace is big (20MB).
672 *
673 * ppoll should work as expected and the trace should be readable at the end.
674 */
675 void ppoll_concurrent_write(void)
676 {
677 int i, ret, fds[MAX_FDS];
678
679 for (i = 0; i < MAX_FDS; i++) {
680 fds[i] = dup(wait_fd);
681 if (fds[i] < 0) {
682 perror("dup");
683 }
684 }
685
686 stress_ppoll(fds, 0);
687 stress_ppoll(fds, 1);
688 stress_ppoll(fds, INT_MAX);
689
690 for (i = 0; i < MAX_FDS; i++) {
691 ret = close(fds[i]);
692 if (ret != 0) {
693 perror("close");
694 }
695 }
696
697 return;
698 }
699
700 void *epoll_pwait_writer(void *addr)
701 {
702 srand(time(NULL));
703
704 while (!stop_thread) {
705 usleep(rand() % 30);
706 munmap(addr, MAX_FDS * sizeof(struct epoll_event));
707 }
708
709 return NULL;
710 }
711
712 /*
713 * epoll_pwait on MAX_FDS fds while a concurrent thread munmaps the
714 * buffer allocated for the returned data. This should randomly segfault.
715 * The trace should be readable and no kernel OOPS should occur.
716 */
717 void epoll_pwait_concurrent_munmap(void)
718 {
719 int ret, epollfd, i, fds[MAX_FDS];
720 char buf[BUF_SIZE];
721 struct epoll_event *epoll_event;
722 void *addr = NULL;
723 pthread_t writer;
724
725
726 epollfd = epoll_create(MAX_FDS);
727 if (epollfd < 0) {
728 perror("[eppoll] create");
729 goto end;
730 }
731
732 epoll_event = mmap(addr, MAX_FDS * sizeof(struct epoll_event),
733 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
734 -1, 0);
735 if (epoll_event == MAP_FAILED) {
736 perror("mmap");
737 goto end;
738 }
739
740 for (i = 0; i < MAX_FDS; i++) {
741 fds[i] = dup(wait_fd);
742 if (fds[i] < 0) {
743 perror("dup");
744 }
745 epoll_event[i].events = EPOLLIN | EPOLLPRI | EPOLLET;
746 epoll_event[i].data.fd = fds[i];
747 ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], epoll_event);
748 if (ret < 0) {
749 perror("[eppoll] add");
750 goto end_unmap;
751 }
752 }
753 stop_thread = 0;
754 pthread_create(&writer, NULL, &epoll_pwait_writer, (void *) epoll_event);
755
756 ret = epoll_pwait(epollfd, epoll_event, 1, 1, NULL);
757
758 if (ret == 1) {
759 printf("# [eppoll] data available\n");
760 ret = read(wait_fd, buf, BUF_SIZE);
761 if (ret < 0) {
762 perror("[eppoll] read");
763 }
764 } else if (ret == 0) {
765 printf("# [eppoll] timeout\n");
766 } else {
767 perror("# epoll_pwait");
768 }
769
770 stop_thread = 1;
771 pthread_join(writer, NULL);
772
773 end_unmap:
774 for (i = 0; i < MAX_FDS; i++) {
775 ret = close(fds[i]);
776 if (ret != 0) {
777 perror("close");
778 }
779 }
780
781 ret = munmap(addr, MAX_FDS * sizeof(struct epoll_event));
782 if (ret != 0) {
783 perror("munmap");
784 }
785
786 end:
787 return;
788 }
789
790 void usage(poptContext optCon, int exitcode, char *error, char *addl)
791 {
792 poptPrintUsage(optCon, stderr, 0);
793 if (error) {
794 fprintf(stderr, "%s: %s\n", error, addl);
795 }
796 exit(exitcode);
797 }
798
799 void print_list(void)
800 {
801 fprintf(stderr, "Test list (-t X):\n");
802 fprintf(stderr, "\t1: Working cases for select, pselect6, poll, ppoll "
803 "and epoll, waiting for input\n");
804 fprintf(stderr, "\t2: Timeout cases (1ms) for select, pselect6, poll, "
805 "ppoll and epoll\n");
806 fprintf(stderr, "\t3: pselect with a FD > 1023\n");
807 fprintf(stderr, "\t4: ppoll with %d FDs\n", MAX_FDS);
808 fprintf(stderr, "\t5: ppoll buffer overflow, should segfault, waits "
809 "for input\n");
810 fprintf(stderr, "\t6: pselect with invalid pointer, waits for "
811 "input\n");
812 fprintf(stderr, "\t7: ppoll with ulong_max fds, waits for input\n");
813 fprintf(stderr, "\t8: epoll_pwait with invalid pointer, waits for "
814 "input\n");
815 fprintf(stderr, "\t9: epoll_pwait with maxevents set to INT_MAX, "
816 "waits for input\n");
817 fprintf(stderr, "\t10: ppoll with concurrent updates of the structure "
818 "from user-space, stress test (3000 iterations), "
819 "waits for input + timeout 1ms\n");
820 fprintf(stderr, "\t11: epoll_pwait with concurrent munmap of the buffer "
821 "from user-space, should randomly segfault, run "
822 "multiple times, waits for input + timeout 1ms\n");
823 }
824
825 int main(int argc, const char **argv)
826 {
827 int c, ret, test = -1;
828 poptContext optCon;
829 struct rlimit open_lim;
830
831 struct poptOption optionsTable[] = {
832 { "test", 't', POPT_ARG_INT, &test, 0,
833 "Test to run", NULL },
834 { "list", 'l', 0, 0, 'l',
835 "List of tests (-t X)", NULL },
836 POPT_AUTOHELP
837 { NULL, 0, 0, NULL, 0 }
838 };
839
840 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
841
842 if (argc < 2) {
843 poptPrintUsage(optCon, stderr, 0);
844 ret = -1;
845 goto end;
846 }
847
848 ret = 0;
849
850 while ((c = poptGetNextOpt(optCon)) >= 0) {
851 switch(c) {
852 case 'l':
853 print_list();
854 goto end;
855 }
856 }
857
858 open_lim.rlim_cur = MAX_FDS + MIN_NR_FDS;
859 open_lim.rlim_max = MAX_FDS + MIN_NR_FDS;
860
861 ret = setrlimit(RLIMIT_NOFILE, &open_lim);
862 if (ret < 0) {
863 perror("setrlimit");
864 goto end;
865 }
866
867 /*
868 * Some tests might segfault, but we need the getpid() to be output
869 * for the validation, disabling the buffering on stdout works.
870 */
871 setbuf(stdout, NULL);
872 printf("%d\n", getpid());
873
874 wait_fd = STDIN_FILENO;
875
876 switch(test) {
877 case 1:
878 timeout = -1;
879 run_working_cases();
880 break;
881 case 2:
882 timeout = 1;
883 run_working_cases();
884 break;
885 case 3:
886 pselect_fd_too_big();
887 break;
888 case 4:
889 test_ppoll_big();
890 break;
891 case 5:
892 ppoll_fds_buffer_overflow();
893 break;
894 case 6:
895 pselect_invalid_pointer();
896 break;
897 case 7:
898 ppoll_fds_ulong_max();
899 break;
900 case 8:
901 epoll_pwait_invalid_pointer();
902 break;
903 case 9:
904 epoll_pwait_int_max();
905 break;
906 case 10:
907 ppoll_concurrent_write();
908 break;
909 case 11:
910 epoll_pwait_concurrent_munmap();
911 break;
912 default:
913 poptPrintUsage(optCon, stderr, 0);
914 ret = -1;
915 break;
916 }
917
918 end:
919 poptFreeContext(optCon);
920 return ret;
921 }
This page took 0.084407 seconds and 5 git commands to generate.