SoW-2019-0002: Dynamic Snapshot
[lttng-tools.git] / tests / regression / kernel / select_poll_epoll.c
1 /*
2 * Copyright (C) 2016 Julien Desfossez <jdesfossez@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
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>
27 #include <common/compat/time.h>
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
40 static int timeout; /* seconds, -1 to disable */
41 static volatile int stop_thread;
42 static int wait_fd;
43
44 struct ppoll_thread_data {
45 struct pollfd *ufds;
46 int value;
47 };
48
49 static void 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
94 end:
95 return;
96 }
97
98 static void 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
131 static void 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
164 static void 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
188 static void 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
220 static void 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
259 static void 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
297 end:
298 return;
299 }
300
301 static void 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
339 end:
340 return;
341 }
342
343 static void 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
380 end:
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 */
389 static void 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 */
420 static void 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 /*
447 * Pass an invalid file descriptor to pselect6(). The syscall should return
448 * -EBADF. The recorded event should contain a "ret = -EBADF (-9)".
449 */
450 static void pselect_invalid_fd(void)
451 {
452 fd_set rfds;
453 int ret;
454 int fd;
455 char buf[BUF_SIZE];
456
457 /*
458 * Open a file, close it and use the closed FD in the pselect6 call.
459 */
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;
471 }
472
473 FD_ZERO(&rfds);
474 FD_SET(fd, &rfds);
475
476 ret = syscall(SYS_pselect6, fd + 1, &rfds, NULL, NULL, NULL, NULL);
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 }
488 error:
489 return;
490 }
491
492 /*
493 * Invalid pointer as writefds, should output a ppoll event
494 * with 0 FDs.
495 */
496 static void 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 */
527 static void 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
563 end:
564 return;
565 }
566
567 /*
568 * Set maxevents to INT_MAX, should output "Invalid argument"
569 * The event should return an empty array.
570 */
571 static void 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
606 end:
607 return;
608 }
609
610 static void *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
623 static void 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
652 static void 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;
672 ret = pthread_join(writer, NULL);
673 if (ret) {
674 fprintf(stderr, "[error] pthread_join\n");
675 goto end;
676 }
677 end:
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 */
693 static void 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
718 static void *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 */
735 static void 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;
740 pthread_t writer;
741
742 for (i = 0; i < MAX_FDS; i++) {
743 fds[i] = -1;
744 }
745 epollfd = epoll_create(MAX_FDS);
746 if (epollfd < 0) {
747 perror("[eppoll] create");
748 goto end;
749 }
750
751 epoll_event = mmap(NULL, MAX_FDS * sizeof(struct epoll_event),
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;
773 ret = pthread_create(&writer, NULL, &epoll_pwait_writer,
774 (void *) epoll_event);
775 if (ret != 0) {
776 fprintf(stderr, "[error] pthread_create\n");
777 goto end_unmap;
778 }
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;
795 ret = pthread_join(writer, NULL);
796 if (ret) {
797 fprintf(stderr, "[error] pthread_join\n");
798 goto end_unmap;
799 }
800 end_unmap:
801 for (i = 0; i < MAX_FDS; i++) {
802 ret = close(fds[i]);
803 if (ret != 0) {
804 perror("close");
805 }
806 }
807
808 ret = munmap(epoll_event, MAX_FDS * sizeof(struct epoll_event));
809 if (ret != 0) {
810 perror("munmap");
811 }
812
813 end:
814 return;
815 }
816
817 static void print_list(void)
818 {
819 fprintf(stderr, "Test list (-t X):\n");
820 fprintf(stderr, "\t1: Working cases for select, pselect6, poll, ppoll "
821 "and epoll, waiting for input\n");
822 fprintf(stderr, "\t2: Timeout cases (1ms) for select, pselect6, poll, "
823 "ppoll and epoll\n");
824 fprintf(stderr, "\t3: pselect with an invalid fd\n");
825 fprintf(stderr, "\t4: ppoll with %d FDs\n", MAX_FDS);
826 fprintf(stderr, "\t5: ppoll buffer overflow, should segfault, waits "
827 "for input\n");
828 fprintf(stderr, "\t6: pselect with an invalid pointer, waits for "
829 "input\n");
830 fprintf(stderr, "\t7: ppoll with ulong_max fds, waits for input\n");
831 fprintf(stderr, "\t8: epoll_pwait with an invalid pointer, waits for "
832 "input\n");
833 fprintf(stderr, "\t9: epoll_pwait with maxevents set to INT_MAX, "
834 "waits for input\n");
835 fprintf(stderr, "\t10: ppoll with concurrent updates of the structure "
836 "from user-space, stress test (3000 iterations), "
837 "waits for input + timeout 1ms\n");
838 fprintf(stderr, "\t11: epoll_pwait with concurrent munmap of the buffer "
839 "from user-space, should randomly segfault, run "
840 "multiple times, waits for input + timeout 1ms\n");
841 }
842
843 int main(int argc, const char **argv)
844 {
845 int c, ret, test = -1;
846 poptContext optCon;
847 struct rlimit open_lim;
848
849 struct poptOption optionsTable[] = {
850 { "test", 't', POPT_ARG_INT, &test, 0,
851 "Test to run", NULL },
852 { "list", 'l', 0, 0, 'l',
853 "List of tests (-t X)", NULL },
854 POPT_AUTOHELP
855 { NULL, 0, 0, NULL, 0 }
856 };
857
858 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
859
860 if (argc < 2) {
861 poptPrintUsage(optCon, stderr, 0);
862 ret = -1;
863 goto end;
864 }
865
866 ret = 0;
867
868 while ((c = poptGetNextOpt(optCon)) >= 0) {
869 switch(c) {
870 case 'l':
871 print_list();
872 goto end;
873 }
874 }
875
876 open_lim.rlim_cur = MAX_FDS + MIN_NR_FDS;
877 open_lim.rlim_max = MAX_FDS + MIN_NR_FDS;
878
879 ret = setrlimit(RLIMIT_NOFILE, &open_lim);
880 if (ret < 0) {
881 perror("setrlimit");
882 goto end;
883 }
884
885 /*
886 * Some tests might segfault, but we need the getpid() to be output
887 * for the validation, disabling the buffering on stdout works.
888 */
889 setbuf(stdout, NULL);
890 printf("%d\n", getpid());
891
892 wait_fd = STDIN_FILENO;
893
894 switch(test) {
895 case 1:
896 timeout = -1;
897 run_working_cases();
898 break;
899 case 2:
900 timeout = 1;
901 run_working_cases();
902 break;
903 case 3:
904 pselect_invalid_fd();
905 break;
906 case 4:
907 test_ppoll_big();
908 break;
909 case 5:
910 ppoll_fds_buffer_overflow();
911 break;
912 case 6:
913 pselect_invalid_pointer();
914 break;
915 case 7:
916 ppoll_fds_ulong_max();
917 break;
918 case 8:
919 epoll_pwait_invalid_pointer();
920 break;
921 case 9:
922 epoll_pwait_int_max();
923 break;
924 case 10:
925 ppoll_concurrent_write();
926 break;
927 case 11:
928 epoll_pwait_concurrent_munmap();
929 break;
930 default:
931 poptPrintUsage(optCon, stderr, 0);
932 ret = -1;
933 break;
934 }
935
936 end:
937 poptFreeContext(optCon);
938 return ret;
939 }
This page took 0.080264 seconds and 5 git commands to generate.