]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/regression/poll/sockpoll.c
Merge llvm-project release/14.x llvmorg-14.0.3-0-g1f9140064dfb
[FreeBSD/FreeBSD.git] / tools / regression / poll / sockpoll.c
1 /* $FreeBSD$ */
2
3 #define _GNU_SOURCE         /* expose POLLRDHUP when testing on Linux */
4
5 #include <sys/socket.h>
6 #include <sys/stat.h>
7
8 #include <err.h>
9 #include <fcntl.h>
10 #include <poll.h>
11 #include <signal.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16
17 static void
18 append(char *out, size_t out_size, const char *s)
19 {
20         size_t size = strlen(out);
21
22         snprintf(out + size, out_size - size, "%s", s);
23 }
24
25 static void
26 decode_events(int events, char *out, size_t out_size)
27 {
28         int unknown;
29
30         out[0] = 0;
31
32         if (events == 0) {
33                 append(out, out_size, "0");
34                 return;
35         }
36
37 #define DECODE_FLAG(x) \
38         if (events & (x)) { \
39                 if (out[0] != 0) \
40                         append(out, out_size, " | "); \
41                 append(out, out_size, #x); \
42         }
43
44         /* Show the expected flags by name. */
45         DECODE_FLAG(POLLIN);
46         DECODE_FLAG(POLLOUT);
47         DECODE_FLAG(POLLHUP);
48 #ifndef POLLRDHUP
49 #define KNOWN_FLAGS (POLLIN | POLLOUT | POLLHUP)
50 #else
51         DECODE_FLAG(POLLRDHUP);
52 #define KNOWN_FLAGS (POLLIN | POLLOUT | POLLHUP | POLLRDHUP);
53 #endif
54
55         /* Show any unexpected bits as hex. */
56         unknown = events & ~KNOWN_FLAGS;
57         if (unknown != 0) {
58                 char buf[80];
59
60                 snprintf(buf, sizeof(buf), "%s%x", out[0] != 0 ? " | " : "",
61                         unknown);
62                 append(out, out_size, buf);
63         }
64 }
65
66 static void
67 report(int num, const char *state, int expected, int got)
68 {
69         char expected_str[80];
70         char got_str[80];
71
72         decode_events(expected, expected_str, sizeof(expected_str));
73         decode_events(got, got_str, sizeof(got_str));
74         if (expected == got)
75                 printf("ok %-2d    ", num);
76         else
77                 printf("not ok %-2d", num);
78         printf(" state %s: expected %s; got %s\n",
79             state, expected_str, got_str);
80         fflush(stdout);
81 }
82
83 static int
84 set_nonblocking(int sck)
85 {
86         int flags;
87
88         flags = fcntl(sck, F_GETFL, 0);
89         flags |= O_NONBLOCK;
90
91         if (fcntl(sck, F_SETFL, flags))
92                 return -1;
93
94         return 0;
95 }
96
97 static char largeblock[1048576]; /* should be more than AF_UNIX sockbuf size */
98 static int fd[2];
99 static struct pollfd pfd0;
100 static struct pollfd pfd1;
101
102 void
103 setup(void)
104 {
105         if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0)
106                 err(1, "socketpair");
107         if (set_nonblocking(fd[0]) == -1)
108                 err(1, "fcntl");
109         if (set_nonblocking(fd[1]) == -1)
110                 err(1, "fcntl");
111         pfd0.fd = fd[0];
112         pfd0.events = POLLIN | POLLOUT;
113         pfd1.fd = fd[1];
114         pfd1.events = POLLIN | POLLOUT;
115 }
116
117 int
118 main(void)
119 {
120         int num;
121
122         num = 1;
123         printf("1..18\n");
124         fflush(stdout);
125
126         /* Large write with close */
127         setup();
128         if (poll(&pfd0, 1, 0) == -1)
129                 err(1, "poll");
130         report(num++, "initial 0", POLLOUT, pfd0.revents);
131         if (poll(&pfd1, 1, 0) == -1)
132                 err(1, "poll");
133         report(num++, "initial 1", POLLOUT, pfd1.revents);
134         if (write(fd[0], largeblock, sizeof(largeblock)) == -1)
135                 err(1, "write");
136         if (poll(&pfd0, 1, 0) == -1)
137                 err(1, "poll");
138         report(num++, "after large write", 0, pfd0.revents);
139         if (poll(&pfd1, 1, 0) == -1)
140                 err(1, "poll");
141         report(num++, "other side after large write", POLLIN | POLLOUT, pfd1.revents);
142         close(fd[0]);
143         if (poll(&pfd1, 1, 0) == -1)
144                 err(1, "poll");
145         report(num++, "other side after close", POLLIN | POLLHUP, pfd1.revents);
146         if (read(fd[1], largeblock, sizeof(largeblock)) == -1)
147                 err(1, "read");
148         if (poll(&pfd1, 1, 0) == -1)
149                 err(1, "poll");
150         report(num++, "other side after reading input", POLLHUP, pfd1.revents);
151         close(fd[1]);
152
153         /* With shutdown(SHUT_WR) */
154         setup();
155         if (shutdown(fd[0], SHUT_WR) == -1)
156                 err(1, "shutdown");
157         if (poll(&pfd0, 1, 0) == -1)
158                 err(1, "poll");
159         report(num++, "after shutdown(SHUT_WR)", POLLOUT, pfd0.revents);
160         if (poll(&pfd1, 1, 0) == -1)
161                 err(1, "poll");
162         report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
163         switch (read(fd[1], largeblock, sizeof(largeblock))) {
164                 case 0:
165                         break;
166                 case -1:
167                         err(1, "read after other side shutdown");
168                         break;
169                 default:
170                         errx(1, "kernel made up data that was never written");
171         }
172         if (poll(&pfd1, 1, 0) == -1)
173                 err(1, "poll");
174         report(num++, "other side after reading EOF", POLLIN | POLLOUT, pfd1.revents);
175         if (write(fd[1], largeblock, sizeof(largeblock)) == -1)
176                 err(1, "write");
177         if (poll(&pfd0, 1, 0) == -1)
178                 err(1, "poll");
179         report(num++, "after data from other side", POLLIN | POLLOUT, pfd0.revents);
180         if (poll(&pfd1, 1, 0) == -1)
181                 err(1, "poll");
182         report(num++, "after writing", POLLIN, pfd1.revents);
183         if (shutdown(fd[1], SHUT_WR) == -1)
184                 err(1, "shutdown second");
185         if (poll(&pfd0, 1, 0) == -1)
186                 err(1, "poll");
187         report(num++, "after second shutdown", POLLIN | POLLHUP, pfd0.revents);
188         if (poll(&pfd1, 1, 0) == -1)
189                 err(1, "poll");
190         report(num++, "after second shutdown", POLLHUP, pfd1.revents);
191         close(fd[0]);
192         if (poll(&pfd1, 1, 0) == -1)
193                 err(1, "poll");
194         report(num++, "after close", POLLHUP, pfd1.revents);
195         close(fd[1]);
196
197         /*
198          * With shutdown(SHUT_RD)
199          * Note that shutdown(SHUT_WR) is passed to the peer, but
200          * shutdown(SHUT_RD) is not.
201          */
202         setup();
203         if (shutdown(fd[0], SHUT_RD) == -1)
204                 err(1, "shutdown");
205         if (poll(&pfd0, 1, 0) == -1)
206                 err(1, "poll");
207         report(num++, "after shutdown(SHUT_RD)", POLLIN | POLLOUT, pfd0.revents);
208         if (poll(&pfd1, 1, 0) == -1)
209                 err(1, "poll");
210         report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, pfd1.revents);
211         if (shutdown(fd[0], SHUT_WR) == -1)
212                 err(1, "shutdown");
213         if (poll(&pfd0, 1, 0) == -1)
214                 err(1, "poll");
215         report(num++, "after shutdown(SHUT_WR)", POLLHUP, pfd0.revents);
216         if (poll(&pfd1, 1, 0) == -1)
217                 err(1, "poll");
218         report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
219         close(fd[0]);
220         close(fd[1]);
221
222 #ifdef POLLRDHUP
223         setup();
224         pfd1.events |= POLLRDHUP;
225         if (shutdown(fd[0], SHUT_RD) == -1)
226                 err(1, "shutdown");
227         if (poll(&pfd1, 1, 0) == -1)
228                 err(1, "poll");
229         report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, pfd1.revents);
230         if (write(fd[0], "x", 1) != 1)
231                 err(1, "write");
232         if (poll(&pfd1, 1, 0) == -1)
233                 err(1, "poll");
234         report(num++, "other side after write", POLLIN | POLLOUT, pfd1.revents);
235         if (shutdown(fd[0], SHUT_WR) == -1)
236                 err(1, "shutdown");
237         if (poll(&pfd1, 1, 0) == -1)
238                 err(1, "poll");
239         report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT | POLLRDHUP, pfd1.revents);
240         close(fd[0]);
241         close(fd[1]);
242 #endif
243
244         return (0);
245 }