]> granicus.if.org Git - strace/blob - tests/poll.c
strace: terminate itself if interrupted by a signal
[strace] / tests / poll.c
1 /*
2  * Check decoding of poll syscall.
3  *
4  * Copyright (c) 2016-2018 Dmitry V. Levin <ldv@altlinux.org>
5  * All rights reserved.
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9
10 #include "tests.h"
11 #include <asm/unistd.h>
12
13 #ifdef __NR_poll
14
15 # include <assert.h>
16 # include <errno.h>
17 # include <poll.h>
18 # include <stdio.h>
19 # include <stdlib.h>
20 # include <string.h>
21 # include <unistd.h>
22
23 #define PRINT_EVENT(flag, member)                       \
24         do {                                            \
25                 if (member & flag) {                    \
26                         if (member != pfd->member)      \
27                                 tprintf("|");           \
28                         tprintf(#flag);                 \
29                         member &= ~flag;                \
30                 }                                       \
31         } while (0)
32
33 static void
34 print_pollfd_entering(const struct pollfd *const pfd)
35 {
36         tprintf("{fd=%d", pfd->fd);
37         if (pfd->fd >= 0) {
38                 tprintf(", events=");
39                 short events = pfd->events;
40
41                 if (pfd->events) {
42                         PRINT_EVENT(POLLIN, events);
43                         PRINT_EVENT(POLLPRI, events);
44                         PRINT_EVENT(POLLOUT, events);
45 #ifdef POLLRDNORM
46                         PRINT_EVENT(POLLRDNORM, events);
47 #endif
48 #ifdef POLLWRNORM
49                         PRINT_EVENT(POLLWRNORM, events);
50 #endif
51 #ifdef POLLRDBAND
52                         PRINT_EVENT(POLLRDBAND, events);
53 #endif
54 #ifdef POLLWRBAND
55                         PRINT_EVENT(POLLWRBAND, events);
56 #endif
57                         PRINT_EVENT(POLLERR, events);
58                         PRINT_EVENT(POLLHUP, events);
59                         PRINT_EVENT(POLLNVAL, events);
60                 } else
61                         tprintf("0");
62         }
63         tprintf("}");
64 }
65
66 static void
67 print_pollfd_array_entering(const struct pollfd *const pfd,
68                             const unsigned int size,
69                             const unsigned int valid,
70                             const unsigned int abbrev)
71 {
72         tprintf("[");
73         unsigned int i;
74         for (i = 0; i < size; ++i) {
75                 if (i)
76                         tprintf(", ");
77                 if (i >= valid) {
78                         tprintf("... /* %p */", &pfd[i]);
79                         break;
80                 }
81                 if (i >= abbrev) {
82                         tprintf("...");
83                         break;
84                 }
85                 print_pollfd_entering(&pfd[i]);
86         }
87         tprintf("]");
88 }
89
90 static void
91 print_pollfd_exiting(const struct pollfd *const pfd,
92                      unsigned int *const seen,
93                      const unsigned int abbrev)
94 {
95         if (!pfd->revents || pfd->fd < 0 || *seen > abbrev)
96                 return;
97
98         if (*seen)
99                 tprintf(", ");
100         ++(*seen);
101
102         if (*seen > abbrev) {
103                 tprintf("...");
104                 return;
105         }
106         tprintf("{fd=%d, revents=", pfd->fd);
107         short revents = pfd->revents;
108
109         PRINT_EVENT(POLLIN, revents);
110         PRINT_EVENT(POLLPRI, revents);
111         PRINT_EVENT(POLLOUT, revents);
112 #ifdef POLLRDNORM
113         PRINT_EVENT(POLLRDNORM, revents);
114 #endif
115 #ifdef POLLWRNORM
116         PRINT_EVENT(POLLWRNORM, revents);
117 #endif
118 #ifdef POLLRDBAND
119         PRINT_EVENT(POLLRDBAND, revents);
120 #endif
121 #ifdef POLLWRBAND
122         PRINT_EVENT(POLLWRBAND, revents);
123 #endif
124         PRINT_EVENT(POLLERR, revents);
125         PRINT_EVENT(POLLHUP, revents);
126         PRINT_EVENT(POLLNVAL, revents);
127         tprintf("}");
128 }
129
130 static void
131 print_pollfd_array_exiting(const struct pollfd *const pfd,
132                            const unsigned int size,
133                            const unsigned int abbrev)
134 {
135         tprintf("[");
136         unsigned int seen = 0;
137         unsigned int i;
138         for (i = 0; i < size; ++i)
139                 print_pollfd_exiting(&pfd[i], &seen, abbrev);
140         tprintf("]");
141 }
142
143 int
144 main(int ac, char **av)
145 {
146 # ifdef PATH_TRACING_FD
147         skip_if_unavailable("/proc/self/fd/");
148 # endif
149
150         tprintf("%s", "");
151
152         assert(syscall(__NR_poll, NULL, 42, 0) == -1);
153         if (ENOSYS == errno)
154                 perror_msg_and_skip("poll");
155
156 # ifndef PATH_TRACING_FD
157         tprintf("poll(NULL, 42, 0) = -1 EFAULT (%m)\n");
158 # endif
159
160         int fds[2];
161         if (pipe(fds) || pipe(fds))
162                 perror_msg_and_fail("pipe");
163
164         const unsigned int abbrev = (ac > 1) ? atoi(av[1]) : -1;
165         const struct pollfd pfds0[] = {
166                 { .fd = 0, .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND },
167                 { .fd = 1, .events = POLLOUT | POLLWRNORM | POLLWRBAND },
168                 { .fd = fds[0], .events = POLLIN | POLLPRI },
169                 { .fd = fds[1], .events = POLLOUT },
170                 { .fd = 2, .events = POLLOUT | POLLWRBAND }
171         };
172         struct pollfd *const tail_fds0 = tail_memdup(pfds0, sizeof(pfds0));
173         const int timeout = 42;
174         int rc = syscall(__NR_poll, tail_fds0, 0, timeout);
175         assert(rc == 0);
176
177 # ifndef PATH_TRACING_FD
178         tprintf("poll([], 0, %d) = %d (Timeout)\n", timeout, rc);
179 # endif
180
181         rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
182         assert(rc == 3);
183
184 # ifndef PATH_TRACING_FD
185         tprintf("poll(");
186         print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
187                                     ARRAY_SIZE(pfds0), abbrev);
188         tprintf(", %u, %d) = %d (",
189                 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
190         print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
191         tprintf(")\n");
192 # endif /* !PATH_TRACING_FD */
193
194         tail_fds0[0].fd = -1;
195         tail_fds0[2].fd = -3;
196         tail_fds0[4].events = 0;
197         rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
198         assert(rc == 2);
199
200 # ifndef PATH_TRACING_FD
201         tprintf("poll(");
202         print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
203                                     ARRAY_SIZE(pfds0), abbrev);
204         tprintf(", %u, %d) = %d (",
205                 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
206         print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
207         tprintf(")\n");
208 # endif /* !PATH_TRACING_FD */
209
210         tail_fds0[1].fd = -2;
211         tail_fds0[4].fd = -5;
212         rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
213         assert(rc == 1);
214
215 # ifndef PATH_TRACING_FD
216         tprintf("poll(");
217         print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
218                                     ARRAY_SIZE(pfds0), abbrev);
219         tprintf(", %u, %d) = %d (",
220                 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
221         print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
222         tprintf(")\n");
223 # endif /* !PATH_TRACING_FD */
224
225         struct pollfd pfds1[] = {
226                 { .fd = 1, .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND },
227                 { .fd = 0, .events = POLLOUT | POLLWRNORM | POLLWRBAND }
228         };
229         struct pollfd *const tail_fds1 = tail_memdup(pfds1, sizeof(pfds1));
230         rc = syscall(__NR_poll, tail_fds1, ARRAY_SIZE(pfds1), timeout);
231         assert(rc == 0);
232
233 # ifndef PATH_TRACING_FD
234         tprintf("poll(");
235         print_pollfd_array_entering(tail_fds1, ARRAY_SIZE(pfds1),
236                                     ARRAY_SIZE(pfds1), abbrev);
237         tprintf(", %u, %d) = %d (Timeout)\n",
238                 (unsigned int) ARRAY_SIZE(pfds1), timeout, rc);
239 # endif /* !PATH_TRACING_FD */
240
241         const void *const efault = tail_fds0 + ARRAY_SIZE(pfds0);
242         rc = syscall(__NR_poll, efault, 1, 0);
243         assert(rc == -1);
244
245 # ifndef PATH_TRACING_FD
246         tprintf("poll(%p, 1, 0) = -1 EFAULT (%m)\n", efault);
247 # endif
248
249         const unsigned int valid = 1;
250         const void *const epfds = tail_fds0 + ARRAY_SIZE(pfds0) - valid;
251         rc = syscall(__NR_poll, epfds, valid + 1, 0);
252         assert(rc == -1);
253
254 # ifndef PATH_TRACING_FD
255         tprintf("poll(");
256         print_pollfd_array_entering(epfds, valid + 1, valid, abbrev);
257         errno = EFAULT;
258         tprintf(", %u, 0) = -1 EFAULT (%m)\n", valid + 1);
259 # endif /* !PATH_TRACING_FD */
260
261 # ifdef PATH_TRACING_FD
262         memcpy(tail_fds0, pfds0, sizeof(pfds0));
263         tail_fds0[4].fd = PATH_TRACING_FD;
264
265         rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
266         assert(rc == 3);
267
268         tprintf("poll(");
269         print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
270                                     ARRAY_SIZE(pfds0), abbrev);
271         tprintf(", %u, %d) = %d (",
272                 (unsigned int) ARRAY_SIZE(pfds0), timeout, rc);
273         print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
274         tprintf(")\n");
275
276         rc = syscall(__NR_poll, epfds, valid + 1, 0);
277         assert(rc == -1);
278
279         /* the 1st pollfd element is readable and contains PATH_TRACING_FD */
280         tprintf("poll(");
281         print_pollfd_array_entering(epfds, valid + 1, valid, abbrev);
282         errno = EFAULT;
283         tprintf(", %u, 0) = -1 EFAULT (%m)\n", valid + 1);
284 # endif /* PATH_TRACING_FD */
285
286         tprintf("+++ exited with 0 +++\n");
287         return 0;
288 }
289
290 #else
291
292 SKIP_MAIN_UNDEFINED("__NR_poll")
293
294 #endif