1 /* $FreeBSD: stable/12/tools/regression/poll/sockpoll.c 196554 2009-08-25 20:33:37Z jilles $ */
2
3 #include <sys/poll.h>
4 #include <sys/socket.h>
5 #include <sys/stat.h>
6
7 #include <err.h>
8 #include <fcntl.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13
14 static const char *
decode_events(int events)15 decode_events(int events)
16 {
17 char *ncresult;
18 const char *result;
19
20 switch (events) {
21 case POLLIN:
22 result = "POLLIN";
23 break;
24 case POLLOUT:
25 result = "POLLOUT";
26 break;
27 case POLLIN | POLLOUT:
28 result = "POLLIN | POLLOUT";
29 break;
30 case POLLHUP:
31 result = "POLLHUP";
32 break;
33 case POLLIN | POLLHUP:
34 result = "POLLIN | POLLHUP";
35 break;
36 case POLLOUT | POLLHUP:
37 result = "POLLOUT | POLLHUP";
38 break;
39 case POLLIN | POLLOUT | POLLHUP:
40 result = "POLLIN | POLLOUT | POLLHUP";
41 break;
42 default:
43 asprintf(&ncresult, "%#x", events);
44 result = ncresult;
45 break;
46 }
47 return (result);
48 }
49
50 static void
report(int num,const char * state,int expected,int got)51 report(int num, const char *state, int expected, int got)
52 {
53 if (expected == got)
54 printf("ok %-2d ", num);
55 else
56 printf("not ok %-2d", num);
57 printf(" state %s: expected %s; got %s\n",
58 state, decode_events(expected), decode_events(got));
59 fflush(stdout);
60 }
61
62 static int
set_nonblocking(int sck)63 set_nonblocking(int sck)
64 {
65 int flags;
66
67 flags = fcntl(sck, F_GETFL, 0);
68 flags |= O_NONBLOCK;
69
70 if (fcntl(sck, F_SETFL, flags))
71 return -1;
72
73 return 0;
74 }
75
76 static char largeblock[1048576]; /* should be more than AF_UNIX sockbuf size */
77 static int fd[2];
78 static struct pollfd pfd0;
79 static struct pollfd pfd1;
80
81 void
setup(void)82 setup(void)
83 {
84 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0)
85 err(1, "socketpair");
86 if (set_nonblocking(fd[0]) == -1)
87 err(1, "fcntl");
88 if (set_nonblocking(fd[1]) == -1)
89 err(1, "fcntl");
90 pfd0.fd = fd[0];
91 pfd0.events = POLLIN | POLLOUT;
92 pfd1.fd = fd[1];
93 pfd1.events = POLLIN | POLLOUT;
94 }
95
96 int
main(void)97 main(void)
98 {
99 int num;
100
101 num = 1;
102 printf("1..18\n");
103 fflush(stdout);
104
105 /* Large write with close */
106 setup();
107 if (poll(&pfd0, 1, 0) == -1)
108 err(1, "poll");
109 report(num++, "initial 0", POLLOUT, pfd0.revents);
110 if (poll(&pfd1, 1, 0) == -1)
111 err(1, "poll");
112 report(num++, "initial 1", POLLOUT, pfd1.revents);
113 if (write(fd[0], largeblock, sizeof(largeblock)) == -1)
114 err(1, "write");
115 if (poll(&pfd0, 1, 0) == -1)
116 err(1, "poll");
117 report(num++, "after large write", 0, pfd0.revents);
118 if (poll(&pfd1, 1, 0) == -1)
119 err(1, "poll");
120 report(num++, "other side after large write", POLLIN | POLLOUT, pfd1.revents);
121 close(fd[0]);
122 if (poll(&pfd1, 1, 0) == -1)
123 err(1, "poll");
124 report(num++, "other side after close", POLLIN | POLLHUP, pfd1.revents);
125 if (read(fd[1], largeblock, sizeof(largeblock)) == -1)
126 err(1, "read");
127 if (poll(&pfd1, 1, 0) == -1)
128 err(1, "poll");
129 report(num++, "other side after reading input", POLLHUP, pfd1.revents);
130 close(fd[1]);
131
132 /* With shutdown(SHUT_WR) */
133 setup();
134 if (shutdown(fd[0], SHUT_WR) == -1)
135 err(1, "shutdown");
136 if (poll(&pfd0, 1, 0) == -1)
137 err(1, "poll");
138 report(num++, "after shutdown(SHUT_WR)", POLLOUT, pfd0.revents);
139 if (poll(&pfd1, 1, 0) == -1)
140 err(1, "poll");
141 report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
142 switch (read(fd[1], largeblock, sizeof(largeblock))) {
143 case 0:
144 break;
145 case -1:
146 err(1, "read after other side shutdown");
147 break;
148 default:
149 errx(1, "kernel made up data that was never written");
150 }
151 if (poll(&pfd1, 1, 0) == -1)
152 err(1, "poll");
153 report(num++, "other side after reading EOF", POLLIN | POLLOUT, pfd1.revents);
154 if (write(fd[1], largeblock, sizeof(largeblock)) == -1)
155 err(1, "write");
156 if (poll(&pfd0, 1, 0) == -1)
157 err(1, "poll");
158 report(num++, "after data from other side", POLLIN | POLLOUT, pfd0.revents);
159 if (poll(&pfd1, 1, 0) == -1)
160 err(1, "poll");
161 report(num++, "after writing", POLLIN, pfd1.revents);
162 if (shutdown(fd[1], SHUT_WR) == -1)
163 err(1, "shutdown second");
164 if (poll(&pfd0, 1, 0) == -1)
165 err(1, "poll");
166 report(num++, "after second shutdown", POLLIN | POLLHUP, pfd0.revents);
167 if (poll(&pfd1, 1, 0) == -1)
168 err(1, "poll");
169 report(num++, "after second shutdown", POLLHUP, pfd1.revents);
170 close(fd[0]);
171 if (poll(&pfd1, 1, 0) == -1)
172 err(1, "poll");
173 report(num++, "after close", POLLHUP, pfd1.revents);
174 close(fd[1]);
175
176 /*
177 * With shutdown(SHUT_RD)
178 * Note that shutdown(SHUT_WR) is passed to the peer, but
179 * shutdown(SHUT_RD) is not.
180 */
181 setup();
182 if (shutdown(fd[0], SHUT_RD) == -1)
183 err(1, "shutdown");
184 if (poll(&pfd0, 1, 0) == -1)
185 err(1, "poll");
186 report(num++, "after shutdown(SHUT_RD)", POLLIN | POLLOUT, pfd0.revents);
187 if (poll(&pfd1, 1, 0) == -1)
188 err(1, "poll");
189 report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, pfd1.revents);
190 if (shutdown(fd[0], SHUT_WR) == -1)
191 err(1, "shutdown");
192 if (poll(&pfd0, 1, 0) == -1)
193 err(1, "poll");
194 report(num++, "after shutdown(SHUT_WR)", POLLHUP, pfd0.revents);
195 if (poll(&pfd1, 1, 0) == -1)
196 err(1, "poll");
197 report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
198 close(fd[0]);
199 close(fd[1]);
200
201 return (0);
202 }
203