xref: /freebsd/tools/regression/poll/sockpoll.c (revision 2a63c3be)
1e9d90c51SJilles Tjoelker 
218f21f03SThomas Munro #define _GNU_SOURCE         /* expose POLLRDHUP when testing on Linux */
318f21f03SThomas Munro 
4e9d90c51SJilles Tjoelker #include <sys/socket.h>
5e9d90c51SJilles Tjoelker #include <sys/stat.h>
6e9d90c51SJilles Tjoelker 
7e9d90c51SJilles Tjoelker #include <err.h>
8e9d90c51SJilles Tjoelker #include <fcntl.h>
918f21f03SThomas Munro #include <poll.h>
10e9d90c51SJilles Tjoelker #include <signal.h>
11e9d90c51SJilles Tjoelker #include <stdio.h>
12e9d90c51SJilles Tjoelker #include <stdlib.h>
1318f21f03SThomas Munro #include <string.h>
14e9d90c51SJilles Tjoelker #include <unistd.h>
15e9d90c51SJilles Tjoelker 
1618f21f03SThomas Munro static void
append(char * out,size_t out_size,const char * s)1718f21f03SThomas Munro append(char *out, size_t out_size, const char *s)
18e9d90c51SJilles Tjoelker {
1918f21f03SThomas Munro 	size_t size = strlen(out);
20e9d90c51SJilles Tjoelker 
2118f21f03SThomas Munro 	snprintf(out + size, out_size - size, "%s", s);
22e9d90c51SJilles Tjoelker }
2318f21f03SThomas Munro 
2418f21f03SThomas Munro static void
decode_events(int events,char * out,size_t out_size)2518f21f03SThomas Munro decode_events(int events, char *out, size_t out_size)
2618f21f03SThomas Munro {
2718f21f03SThomas Munro 	int unknown;
2818f21f03SThomas Munro 
2918f21f03SThomas Munro 	out[0] = 0;
3018f21f03SThomas Munro 
3118f21f03SThomas Munro 	if (events == 0) {
3218f21f03SThomas Munro 		append(out, out_size, "0");
3318f21f03SThomas Munro 		return;
3418f21f03SThomas Munro 	}
3518f21f03SThomas Munro 
3618f21f03SThomas Munro #define DECODE_FLAG(x) \
3718f21f03SThomas Munro 	if (events & (x)) { \
3818f21f03SThomas Munro 		if (out[0] != 0) \
3918f21f03SThomas Munro 			append(out, out_size, " | "); \
4018f21f03SThomas Munro 		append(out, out_size, #x); \
4118f21f03SThomas Munro 	}
4218f21f03SThomas Munro 
4318f21f03SThomas Munro 	/* Show the expected flags by name. */
4418f21f03SThomas Munro 	DECODE_FLAG(POLLIN);
4518f21f03SThomas Munro 	DECODE_FLAG(POLLOUT);
4618f21f03SThomas Munro 	DECODE_FLAG(POLLHUP);
4718f21f03SThomas Munro #ifndef POLLRDHUP
4818f21f03SThomas Munro #define KNOWN_FLAGS (POLLIN | POLLOUT | POLLHUP)
4918f21f03SThomas Munro #else
5018f21f03SThomas Munro 	DECODE_FLAG(POLLRDHUP);
5118f21f03SThomas Munro #define KNOWN_FLAGS (POLLIN | POLLOUT | POLLHUP | POLLRDHUP);
5218f21f03SThomas Munro #endif
5318f21f03SThomas Munro 
5418f21f03SThomas Munro 	/* Show any unexpected bits as hex. */
5518f21f03SThomas Munro 	unknown = events & ~KNOWN_FLAGS;
5618f21f03SThomas Munro 	if (unknown != 0) {
5718f21f03SThomas Munro 		char buf[80];
5818f21f03SThomas Munro 
5918f21f03SThomas Munro 		snprintf(buf, sizeof(buf), "%s%x", out[0] != 0 ? " | " : "",
6018f21f03SThomas Munro 			unknown);
6118f21f03SThomas Munro 		append(out, out_size, buf);
6218f21f03SThomas Munro 	}
63e9d90c51SJilles Tjoelker }
64e9d90c51SJilles Tjoelker 
65e9d90c51SJilles Tjoelker static void
report(int num,const char * state,int expected,int got)66e9d90c51SJilles Tjoelker report(int num, const char *state, int expected, int got)
67e9d90c51SJilles Tjoelker {
6818f21f03SThomas Munro 	char expected_str[80];
6918f21f03SThomas Munro 	char got_str[80];
7018f21f03SThomas Munro 
7118f21f03SThomas Munro 	decode_events(expected, expected_str, sizeof(expected_str));
7218f21f03SThomas Munro 	decode_events(got, got_str, sizeof(got_str));
73e9d90c51SJilles Tjoelker 	if (expected == got)
74e9d90c51SJilles Tjoelker 		printf("ok %-2d    ", num);
75e9d90c51SJilles Tjoelker 	else
76e9d90c51SJilles Tjoelker 		printf("not ok %-2d", num);
77e9d90c51SJilles Tjoelker 	printf(" state %s: expected %s; got %s\n",
7818f21f03SThomas Munro 	    state, expected_str, got_str);
79e9d90c51SJilles Tjoelker 	fflush(stdout);
80e9d90c51SJilles Tjoelker }
81e9d90c51SJilles Tjoelker 
82e9d90c51SJilles Tjoelker static int
set_nonblocking(int sck)83e9d90c51SJilles Tjoelker set_nonblocking(int sck)
84e9d90c51SJilles Tjoelker {
85e9d90c51SJilles Tjoelker 	int flags;
86e9d90c51SJilles Tjoelker 
87e9d90c51SJilles Tjoelker 	flags = fcntl(sck, F_GETFL, 0);
88e9d90c51SJilles Tjoelker 	flags |= O_NONBLOCK;
89e9d90c51SJilles Tjoelker 
90e9d90c51SJilles Tjoelker 	if (fcntl(sck, F_SETFL, flags))
91e9d90c51SJilles Tjoelker 		return -1;
92e9d90c51SJilles Tjoelker 
93e9d90c51SJilles Tjoelker 	return 0;
94e9d90c51SJilles Tjoelker }
95e9d90c51SJilles Tjoelker 
96e9d90c51SJilles Tjoelker static char largeblock[1048576]; /* should be more than AF_UNIX sockbuf size */
97e9d90c51SJilles Tjoelker static int fd[2];
98e9d90c51SJilles Tjoelker static struct pollfd pfd0;
99e9d90c51SJilles Tjoelker static struct pollfd pfd1;
100e9d90c51SJilles Tjoelker 
101e9d90c51SJilles Tjoelker void
setup(void)102e9d90c51SJilles Tjoelker setup(void)
103e9d90c51SJilles Tjoelker {
104e9d90c51SJilles Tjoelker 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0)
105e9d90c51SJilles Tjoelker 		err(1, "socketpair");
106e9d90c51SJilles Tjoelker 	if (set_nonblocking(fd[0]) == -1)
107e9d90c51SJilles Tjoelker 		err(1, "fcntl");
108e9d90c51SJilles Tjoelker 	if (set_nonblocking(fd[1]) == -1)
109e9d90c51SJilles Tjoelker 		err(1, "fcntl");
110e9d90c51SJilles Tjoelker 	pfd0.fd = fd[0];
111e9d90c51SJilles Tjoelker 	pfd0.events = POLLIN | POLLOUT;
112e9d90c51SJilles Tjoelker 	pfd1.fd = fd[1];
113e9d90c51SJilles Tjoelker 	pfd1.events = POLLIN | POLLOUT;
114e9d90c51SJilles Tjoelker }
115e9d90c51SJilles Tjoelker 
116e9d90c51SJilles Tjoelker int
main(void)117e9d90c51SJilles Tjoelker main(void)
118e9d90c51SJilles Tjoelker {
119e9d90c51SJilles Tjoelker 	int num;
120e9d90c51SJilles Tjoelker 
121e9d90c51SJilles Tjoelker 	num = 1;
122e9d90c51SJilles Tjoelker 	printf("1..18\n");
123e9d90c51SJilles Tjoelker 	fflush(stdout);
124e9d90c51SJilles Tjoelker 
125e9d90c51SJilles Tjoelker 	/* Large write with close */
126e9d90c51SJilles Tjoelker 	setup();
127e9d90c51SJilles Tjoelker 	if (poll(&pfd0, 1, 0) == -1)
128e9d90c51SJilles Tjoelker 		err(1, "poll");
129e9d90c51SJilles Tjoelker 	report(num++, "initial 0", POLLOUT, pfd0.revents);
130e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
131e9d90c51SJilles Tjoelker 		err(1, "poll");
132e9d90c51SJilles Tjoelker 	report(num++, "initial 1", POLLOUT, pfd1.revents);
133e9d90c51SJilles Tjoelker 	if (write(fd[0], largeblock, sizeof(largeblock)) == -1)
134e9d90c51SJilles Tjoelker 		err(1, "write");
135e9d90c51SJilles Tjoelker 	if (poll(&pfd0, 1, 0) == -1)
136e9d90c51SJilles Tjoelker 		err(1, "poll");
137e9d90c51SJilles Tjoelker 	report(num++, "after large write", 0, pfd0.revents);
138e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
139e9d90c51SJilles Tjoelker 		err(1, "poll");
140e9d90c51SJilles Tjoelker 	report(num++, "other side after large write", POLLIN | POLLOUT, pfd1.revents);
141e9d90c51SJilles Tjoelker 	close(fd[0]);
142e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
143e9d90c51SJilles Tjoelker 		err(1, "poll");
144e9d90c51SJilles Tjoelker 	report(num++, "other side after close", POLLIN | POLLHUP, pfd1.revents);
145e9d90c51SJilles Tjoelker 	if (read(fd[1], largeblock, sizeof(largeblock)) == -1)
146e9d90c51SJilles Tjoelker 		err(1, "read");
147e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
148e9d90c51SJilles Tjoelker 		err(1, "poll");
149e9d90c51SJilles Tjoelker 	report(num++, "other side after reading input", POLLHUP, pfd1.revents);
150e9d90c51SJilles Tjoelker 	close(fd[1]);
151e9d90c51SJilles Tjoelker 
152e9d90c51SJilles Tjoelker 	/* With shutdown(SHUT_WR) */
153e9d90c51SJilles Tjoelker 	setup();
154e9d90c51SJilles Tjoelker 	if (shutdown(fd[0], SHUT_WR) == -1)
155e9d90c51SJilles Tjoelker 		err(1, "shutdown");
156e9d90c51SJilles Tjoelker 	if (poll(&pfd0, 1, 0) == -1)
157e9d90c51SJilles Tjoelker 		err(1, "poll");
158e9d90c51SJilles Tjoelker 	report(num++, "after shutdown(SHUT_WR)", POLLOUT, pfd0.revents);
159e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
160e9d90c51SJilles Tjoelker 		err(1, "poll");
161e9d90c51SJilles Tjoelker 	report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
162e9d90c51SJilles Tjoelker 	switch (read(fd[1], largeblock, sizeof(largeblock))) {
163e9d90c51SJilles Tjoelker 		case 0:
164e9d90c51SJilles Tjoelker 			break;
165e9d90c51SJilles Tjoelker 		case -1:
166e9d90c51SJilles Tjoelker 			err(1, "read after other side shutdown");
167e9d90c51SJilles Tjoelker 			break;
168e9d90c51SJilles Tjoelker 		default:
169e9d90c51SJilles Tjoelker 			errx(1, "kernel made up data that was never written");
170e9d90c51SJilles Tjoelker 	}
171e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
172e9d90c51SJilles Tjoelker 		err(1, "poll");
173e9d90c51SJilles Tjoelker 	report(num++, "other side after reading EOF", POLLIN | POLLOUT, pfd1.revents);
174e9d90c51SJilles Tjoelker 	if (write(fd[1], largeblock, sizeof(largeblock)) == -1)
175e9d90c51SJilles Tjoelker 		err(1, "write");
176e9d90c51SJilles Tjoelker 	if (poll(&pfd0, 1, 0) == -1)
177e9d90c51SJilles Tjoelker 		err(1, "poll");
178e9d90c51SJilles Tjoelker 	report(num++, "after data from other side", POLLIN | POLLOUT, pfd0.revents);
179e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
180e9d90c51SJilles Tjoelker 		err(1, "poll");
181e9d90c51SJilles Tjoelker 	report(num++, "after writing", POLLIN, pfd1.revents);
182e9d90c51SJilles Tjoelker 	if (shutdown(fd[1], SHUT_WR) == -1)
183e9d90c51SJilles Tjoelker 		err(1, "shutdown second");
184e9d90c51SJilles Tjoelker 	if (poll(&pfd0, 1, 0) == -1)
185e9d90c51SJilles Tjoelker 		err(1, "poll");
186e9d90c51SJilles Tjoelker 	report(num++, "after second shutdown", POLLIN | POLLHUP, pfd0.revents);
187e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
188e9d90c51SJilles Tjoelker 		err(1, "poll");
189e9d90c51SJilles Tjoelker 	report(num++, "after second shutdown", POLLHUP, pfd1.revents);
190e9d90c51SJilles Tjoelker 	close(fd[0]);
191e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
192e9d90c51SJilles Tjoelker 		err(1, "poll");
193e9d90c51SJilles Tjoelker 	report(num++, "after close", POLLHUP, pfd1.revents);
194e9d90c51SJilles Tjoelker 	close(fd[1]);
195e9d90c51SJilles Tjoelker 
196e9d90c51SJilles Tjoelker 	/*
197e9d90c51SJilles Tjoelker 	 * With shutdown(SHUT_RD)
198e9d90c51SJilles Tjoelker 	 * Note that shutdown(SHUT_WR) is passed to the peer, but
199e9d90c51SJilles Tjoelker 	 * shutdown(SHUT_RD) is not.
200e9d90c51SJilles Tjoelker 	 */
201e9d90c51SJilles Tjoelker 	setup();
202e9d90c51SJilles Tjoelker 	if (shutdown(fd[0], SHUT_RD) == -1)
203e9d90c51SJilles Tjoelker 		err(1, "shutdown");
204e9d90c51SJilles Tjoelker 	if (poll(&pfd0, 1, 0) == -1)
205e9d90c51SJilles Tjoelker 		err(1, "poll");
206e9d90c51SJilles Tjoelker 	report(num++, "after shutdown(SHUT_RD)", POLLIN | POLLOUT, pfd0.revents);
207e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
208e9d90c51SJilles Tjoelker 		err(1, "poll");
209e9d90c51SJilles Tjoelker 	report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, pfd1.revents);
210e9d90c51SJilles Tjoelker 	if (shutdown(fd[0], SHUT_WR) == -1)
211e9d90c51SJilles Tjoelker 		err(1, "shutdown");
212e9d90c51SJilles Tjoelker 	if (poll(&pfd0, 1, 0) == -1)
213e9d90c51SJilles Tjoelker 		err(1, "poll");
214e9d90c51SJilles Tjoelker 	report(num++, "after shutdown(SHUT_WR)", POLLHUP, pfd0.revents);
215e9d90c51SJilles Tjoelker 	if (poll(&pfd1, 1, 0) == -1)
216e9d90c51SJilles Tjoelker 		err(1, "poll");
217e9d90c51SJilles Tjoelker 	report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
218e9d90c51SJilles Tjoelker 	close(fd[0]);
219e9d90c51SJilles Tjoelker 	close(fd[1]);
220e9d90c51SJilles Tjoelker 
22118f21f03SThomas Munro #ifdef POLLRDHUP
22218f21f03SThomas Munro 	setup();
22318f21f03SThomas Munro 	pfd1.events |= POLLRDHUP;
22418f21f03SThomas Munro 	if (shutdown(fd[0], SHUT_RD) == -1)
22518f21f03SThomas Munro 		err(1, "shutdown");
22618f21f03SThomas Munro 	if (poll(&pfd1, 1, 0) == -1)
22718f21f03SThomas Munro 		err(1, "poll");
22818f21f03SThomas Munro 	report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, pfd1.revents);
22918f21f03SThomas Munro 	if (write(fd[0], "x", 1) != 1)
23018f21f03SThomas Munro 		err(1, "write");
23118f21f03SThomas Munro 	if (poll(&pfd1, 1, 0) == -1)
23218f21f03SThomas Munro 		err(1, "poll");
23318f21f03SThomas Munro 	report(num++, "other side after write", POLLIN | POLLOUT, pfd1.revents);
23418f21f03SThomas Munro 	if (shutdown(fd[0], SHUT_WR) == -1)
23518f21f03SThomas Munro 		err(1, "shutdown");
23618f21f03SThomas Munro 	if (poll(&pfd1, 1, 0) == -1)
23718f21f03SThomas Munro 		err(1, "poll");
23818f21f03SThomas Munro 	report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT | POLLRDHUP, pfd1.revents);
23918f21f03SThomas Munro 	close(fd[0]);
24018f21f03SThomas Munro 	close(fd[1]);
24118f21f03SThomas Munro #endif
24218f21f03SThomas Munro 
243e9d90c51SJilles Tjoelker 	return (0);
244e9d90c51SJilles Tjoelker }
245