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