Imported Upstream version 0.3.113
[platform/upstream/libaio.git] / harness / cases / 22.t
1 /*
2  * Copyright (C) 2006-2018 Free Software Foundation, Inc.
3  * Copyright (C) 2018 Christoph Hellwig.
4  * License: LGPLv2.1 or later.
5  *
6  * Description: test aio poll and io_pgetevents signal handling.
7  *
8  * Very roughly based on glibc tst-pselect.c.
9  */
10 #include <errno.h>
11 #include <signal.h>
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <sys/poll.h>
15 #include <sys/wait.h>
16 #include <stdlib.h>
17
18 static volatile int handler_called;
19
20 static void
21 handler(int sig)
22 {
23         handler_called = 1;
24 }
25
26 int test_main(void)
27 {
28         struct timespec to = { .tv_sec = 0, .tv_nsec = 500000000 };
29         pid_t parent = getpid(), p;
30         int pipe1[2], pipe2[2];
31         struct sigaction sa = { .sa_flags = 0 };
32         sigset_t sigmask;
33         struct io_context *ctx = NULL;
34         struct io_event ev;
35         struct iocb iocb;
36         struct iocb *iocbs[] = { &iocb };
37         int ret;
38
39         sigemptyset(&sa.sa_mask);
40
41         sa.sa_handler = handler;
42         if (sigaction(SIGUSR1, &sa, NULL) != 0) {
43                 printf("sigaction(1) failed\n");
44                 return 1;
45         }
46
47         sa.sa_handler = SIG_IGN;
48         if (sigaction(SIGCHLD, &sa, NULL) != 0) {
49                 printf("sigaction(2) failed\n");
50                 return 1;
51         }
52
53         sigemptyset(&sigmask);
54         sigaddset(&sigmask, SIGUSR1);
55         if (sigprocmask(SIG_BLOCK, &sigmask, NULL) != 0) {
56                 printf("sigprocmask failed\n");
57                 return 1;
58         }
59
60         if (pipe(pipe1) != 0 || pipe(pipe2) != 0) {
61                 printf("pipe failed\n");
62                 return 1;
63         }
64
65         sigprocmask(SIG_SETMASK, NULL, &sigmask);
66         sigdelset(&sigmask, SIGUSR1);
67
68         p = fork();
69         switch (p) {
70         case -1:
71                 printf("fork failed\n");
72                 exit(2);
73         case 0:
74                 close(pipe1[1]);
75                 close(pipe2[0]);
76
77                 ret = io_setup(1, &ctx);
78                 if (ret) {
79                         printf("child: io_setup failed: %s\n", strerror(-ret));
80                         return 1;
81                 }
82
83                 io_prep_poll(&iocb, pipe1[0], POLLIN);
84                 ret = io_submit(ctx, 1, iocbs);
85                 if (ret != 1) {
86                         /* if poll isn't supported, skip the test */
87                         if (ret == -EINVAL)
88                                 return 3;
89                         printf("child: io_submit failed: %s\n", strerror(-ret));
90                         return 1;
91                 }
92
93                 do {
94                         if (getppid() != parent) {
95                                 printf("parent died\n");
96                                 exit(2);
97                         }
98                         ret = io_pgetevents(ctx, 1, 1, &ev, &to, &sigmask);
99                 } while (ret == 0);
100
101                 /* SKIP if the syscall has not been implemented. */
102                 if (ret == -ENOSYS)
103                         return 3;
104
105                 if (ret != -EINTR) {
106                         printf("child: io_pgetevents did not set errno to "
107                                "EINTR: %s\n", strerror(-ret));
108                         return 1;
109                 }
110
111                 do {
112                         errno = 0;
113                         ret = write(pipe2[1], "foo", 3);
114                 } while (ret == -1 && errno == EINTR);
115
116                 exit(0);
117         default:
118                 close(pipe1[0]);
119                 close(pipe2[1]);
120
121                 io_prep_poll(&iocb, pipe2[0], POLLIN);
122
123                 ret = io_setup(1, &ctx);
124                 if (ret) {
125                         printf("parent: io_setup failed: %s\n", strerror(-ret));
126                         return 1;
127                 }
128
129                 ret = io_submit(ctx, 1, iocbs);
130                 if (ret != 1) {
131                         /* if poll isn't supported, skip the test */
132                         if (ret == -EINVAL)
133                                 return 3;
134                         printf("parent: io_submit failed with %d: %s\n",
135                                ret, strerror(-ret));
136                         return 1;
137                 }
138
139                 kill(p, SIGUSR1);
140
141                 ret = io_pgetevents(ctx, 1, 1, &ev, NULL, &sigmask);
142                 /* SKIP if the syscall has not been implemented. */
143                 if (ret == -ENOSYS)
144                         return 3;
145                 if (ret < 0) {
146                         printf("parent: io_pgetevents failed: %s\n",
147                                strerror(-ret));
148                         return 1;
149                 }
150                 if (ret != 1) {
151                         printf("parent: io_pgetevents did not report event\n");
152                         return 1;
153                 }
154                 if (ev.obj != &iocb) {
155                         printf("parent: io_pgetevents reports wrong fd\n");
156                         return 1;
157                 }
158                 if ((ev.res & POLLIN) != POLLIN) {
159                         printf("parent: io_pgetevents did not report readable fd\n");
160                         return 1;
161                 }
162
163                 return 0;
164         }
165 }
166 /*
167  * Local variables:
168  *  mode: c
169  *  c-basic-offset: 8
170  * End:
171  */