xref: /freebsd/tools/regression/poll/pipepoll.c (revision 42992a3a9cd2ee5e99e15f5cfa6d217f773513b4)
15861f966SKonstantin Belousov /* $FreeBSD$ */
25861f966SKonstantin Belousov 
35861f966SKonstantin Belousov #include <sys/poll.h>
45861f966SKonstantin Belousov #include <sys/socket.h>
55861f966SKonstantin Belousov #include <sys/stat.h>
65861f966SKonstantin Belousov 
75861f966SKonstantin Belousov #include <err.h>
85861f966SKonstantin Belousov #include <fcntl.h>
95861f966SKonstantin Belousov #include <signal.h>
105861f966SKonstantin Belousov #include <stdio.h>
115861f966SKonstantin Belousov #include <stdlib.h>
125861f966SKonstantin Belousov #include <unistd.h>
135861f966SKonstantin Belousov 
145861f966SKonstantin Belousov #define	FIFONAME	"fifo.tmp"
155861f966SKonstantin Belousov #define	FT_END		3
165861f966SKonstantin Belousov #define	FT_FIFO		2
175861f966SKonstantin Belousov #define	FT_PIPE		0
185861f966SKonstantin Belousov #define	FT_SOCKETPAIR	1
195861f966SKonstantin Belousov 
205861f966SKonstantin Belousov static int filetype;
215861f966SKonstantin Belousov 
225861f966SKonstantin Belousov static const char *
235861f966SKonstantin Belousov decode_events(int events)
245861f966SKonstantin Belousov {
255861f966SKonstantin Belousov 	char *ncresult;
265861f966SKonstantin Belousov 	const char *result;
275861f966SKonstantin Belousov 
285861f966SKonstantin Belousov 	switch (events) {
295861f966SKonstantin Belousov 	case POLLIN:
305861f966SKonstantin Belousov 		result = "POLLIN";
315861f966SKonstantin Belousov 		break;
325861f966SKonstantin Belousov 	case POLLHUP:
335861f966SKonstantin Belousov 		result = "POLLHUP";
345861f966SKonstantin Belousov 		break;
355861f966SKonstantin Belousov 	case POLLIN | POLLHUP:
365861f966SKonstantin Belousov 		result = "POLLIN | POLLHUP";
375861f966SKonstantin Belousov 		break;
385861f966SKonstantin Belousov 	default:
395861f966SKonstantin Belousov 		asprintf(&ncresult, "%#x", events);
405861f966SKonstantin Belousov 		result = ncresult;
415861f966SKonstantin Belousov 		break;
425861f966SKonstantin Belousov 	}
435861f966SKonstantin Belousov 	return (result);
445861f966SKonstantin Belousov }
455861f966SKonstantin Belousov 
465861f966SKonstantin Belousov static void
47*42992a3aSKonstantin Belousov report_state(const char *state)
485861f966SKonstantin Belousov {
49*42992a3aSKonstantin Belousov 
50*42992a3aSKonstantin Belousov 	printf(" %s state %s: ",
51*42992a3aSKonstantin Belousov 	    filetype == FT_PIPE ? "Pipe" :
52*42992a3aSKonstantin Belousov 	    filetype == FT_SOCKETPAIR ? "Sock" : "FIFO",
53*42992a3aSKonstantin Belousov 	    state);
54*42992a3aSKonstantin Belousov }
55*42992a3aSKonstantin Belousov 
56*42992a3aSKonstantin Belousov static void
57*42992a3aSKonstantin Belousov report(int num, const char *state, int expected, int got, int res,
58*42992a3aSKonstantin Belousov     int res_expected)
59*42992a3aSKonstantin Belousov {
60*42992a3aSKonstantin Belousov 
61*42992a3aSKonstantin Belousov 	if (res != res_expected) {
62*42992a3aSKonstantin Belousov 		printf("not ok %-2d", num);
63*42992a3aSKonstantin Belousov 		report_state(state);
64*42992a3aSKonstantin Belousov 		printf("poll result %d expected %d. ",
65*42992a3aSKonstantin Belousov 		    res, res_expected);
66*42992a3aSKonstantin Belousov 	} else {
675861f966SKonstantin Belousov 		if (expected == got)
685861f966SKonstantin Belousov 			printf("ok %-2d    ", num);
695861f966SKonstantin Belousov 		else
705861f966SKonstantin Belousov 			printf("not ok %-2d", num);
71*42992a3aSKonstantin Belousov 		report_state(state);
72*42992a3aSKonstantin Belousov 	}
73*42992a3aSKonstantin Belousov 	printf("expected %s; got %s\n", decode_events(expected),
74*42992a3aSKonstantin Belousov 	    decode_events(got));
755861f966SKonstantin Belousov 	fflush(stdout);
765861f966SKonstantin Belousov }
775861f966SKonstantin Belousov 
785861f966SKonstantin Belousov static pid_t cpid;
795861f966SKonstantin Belousov static pid_t ppid;
805861f966SKonstantin Belousov static volatile sig_atomic_t state;
815861f966SKonstantin Belousov 
825861f966SKonstantin Belousov static void
83*42992a3aSKonstantin Belousov catch(int sig __unused)
845861f966SKonstantin Belousov {
85*42992a3aSKonstantin Belousov 
865861f966SKonstantin Belousov 	state++;
875861f966SKonstantin Belousov }
885861f966SKonstantin Belousov 
895861f966SKonstantin Belousov static void
905861f966SKonstantin Belousov child(int fd, int num)
915861f966SKonstantin Belousov {
925861f966SKonstantin Belousov 	struct pollfd pfd;
93*42992a3aSKonstantin Belousov 	int fd2, res;
945861f966SKonstantin Belousov 	char buf[256];
955861f966SKonstantin Belousov 
965861f966SKonstantin Belousov 	if (filetype == FT_FIFO) {
975861f966SKonstantin Belousov 		fd = open(FIFONAME, O_RDONLY | O_NONBLOCK);
985861f966SKonstantin Belousov 		if (fd < 0)
995861f966SKonstantin Belousov 			err(1, "open for read");
1005861f966SKonstantin Belousov 	}
1015861f966SKonstantin Belousov 	pfd.fd = fd;
1025861f966SKonstantin Belousov 	pfd.events = POLLIN;
1035861f966SKonstantin Belousov 
1045861f966SKonstantin Belousov 	if (filetype == FT_FIFO) {
105*42992a3aSKonstantin Belousov 		if ((res = poll(&pfd, 1, 0)) < 0)
1065861f966SKonstantin Belousov 			err(1, "poll");
107*42992a3aSKonstantin Belousov 		report(num++, "0", 0, pfd.revents, res, 0);
1085861f966SKonstantin Belousov 	}
1095861f966SKonstantin Belousov 	kill(ppid, SIGUSR1);
1105861f966SKonstantin Belousov 
1115861f966SKonstantin Belousov 	usleep(1);
1125861f966SKonstantin Belousov 	while (state != 1)
1135861f966SKonstantin Belousov 		;
1145861f966SKonstantin Belousov 	if (filetype != FT_FIFO) {
1155861f966SKonstantin Belousov 		/*
1165861f966SKonstantin Belousov 		 * The connection cannot be reestablished.  Use the code that
1175861f966SKonstantin Belousov 		 * delays the read until after the writer disconnects since
1185861f966SKonstantin Belousov 		 * that case is more interesting.
1195861f966SKonstantin Belousov 		 */
1205861f966SKonstantin Belousov 		state = 4;
1215861f966SKonstantin Belousov 		goto state4;
1225861f966SKonstantin Belousov 	}
123*42992a3aSKonstantin Belousov 	if ((res = poll(&pfd, 1, 0)) < 0)
1245861f966SKonstantin Belousov 		err(1, "poll");
125*42992a3aSKonstantin Belousov 	report(num++, "1", 0, pfd.revents, res, 0);
1265861f966SKonstantin Belousov 	kill(ppid, SIGUSR1);
1275861f966SKonstantin Belousov 
1285861f966SKonstantin Belousov 	usleep(1);
1295861f966SKonstantin Belousov 	while (state != 2)
1305861f966SKonstantin Belousov 		;
131*42992a3aSKonstantin Belousov 	if ((res = poll(&pfd, 1, 0)) < 0)
1325861f966SKonstantin Belousov 		err(1, "poll");
133*42992a3aSKonstantin Belousov 	report(num++, "2", POLLIN, pfd.revents, res, 1);
1345861f966SKonstantin Belousov 	if (read(fd, buf, sizeof buf) != 1)
1355861f966SKonstantin Belousov 		err(1, "read");
136*42992a3aSKonstantin Belousov 	if ((res = poll(&pfd, 1, 0)) < 0)
1375861f966SKonstantin Belousov 		err(1, "poll");
138*42992a3aSKonstantin Belousov 	report(num++, "2a", 0, pfd.revents, res, 0);
1395861f966SKonstantin Belousov 	kill(ppid, SIGUSR1);
1405861f966SKonstantin Belousov 
1415861f966SKonstantin Belousov 	usleep(1);
1425861f966SKonstantin Belousov 	while (state != 3)
1435861f966SKonstantin Belousov 		;
144*42992a3aSKonstantin Belousov 	if ((res = poll(&pfd, 1, 0)) < 0)
1455861f966SKonstantin Belousov 		err(1, "poll");
146*42992a3aSKonstantin Belousov 	report(num++, "3", POLLHUP, pfd.revents, res, 1);
1475861f966SKonstantin Belousov 	kill(ppid, SIGUSR1);
1485861f966SKonstantin Belousov 
1495861f966SKonstantin Belousov 	/*
1505861f966SKonstantin Belousov 	 * Now we expect a new writer, and a new connection too since
1515861f966SKonstantin Belousov 	 * we read all the data.  The only new point is that we didn't
1525861f966SKonstantin Belousov 	 * start quite from scratch since the read fd is not new.  Check
1535861f966SKonstantin Belousov 	 * startup state as above, but don't do the read as above.
1545861f966SKonstantin Belousov 	 */
1555861f966SKonstantin Belousov 	usleep(1);
1565861f966SKonstantin Belousov 	while (state != 4)
1575861f966SKonstantin Belousov 		;
1585861f966SKonstantin Belousov state4:
159*42992a3aSKonstantin Belousov 	if ((res = poll(&pfd, 1, 0)) < 0)
1605861f966SKonstantin Belousov 		err(1, "poll");
161*42992a3aSKonstantin Belousov 	report(num++, "4", 0, pfd.revents, res, 0);
1625861f966SKonstantin Belousov 	kill(ppid, SIGUSR1);
1635861f966SKonstantin Belousov 
1645861f966SKonstantin Belousov 	usleep(1);
1655861f966SKonstantin Belousov 	while (state != 5)
1665861f966SKonstantin Belousov 		;
167*42992a3aSKonstantin Belousov 	if ((res = poll(&pfd, 1, 0)) < 0)
1685861f966SKonstantin Belousov 		err(1, "poll");
169*42992a3aSKonstantin Belousov 	report(num++, "5", POLLIN, pfd.revents, res, 1);
1705861f966SKonstantin Belousov 	kill(ppid, SIGUSR1);
1715861f966SKonstantin Belousov 
1725861f966SKonstantin Belousov 	usleep(1);
1735861f966SKonstantin Belousov 	while (state != 6)
1745861f966SKonstantin Belousov 		;
1755861f966SKonstantin Belousov 	/*
1765861f966SKonstantin Belousov 	 * Now we have no writer, but should still have data from the old
1775861f966SKonstantin Belousov 	 * writer.  Check that we have both a data-readable condition and a
1785861f966SKonstantin Belousov 	 * hangup condition, and that the data can be read in the usual way.
1795861f966SKonstantin Belousov 	 * Since Linux does this, programs must not quit reading when they
1805861f966SKonstantin Belousov 	 * see POLLHUP; they must see POLLHUP without POLLIN (or another
1815861f966SKonstantin Belousov 	 * input condition) before they decide that there is EOF.  gdb-6.1.1
1825861f966SKonstantin Belousov 	 * is an example of a broken program that quits on POLLHUP only --
1835861f966SKonstantin Belousov 	 * see its event-loop.c.
1845861f966SKonstantin Belousov 	 */
185*42992a3aSKonstantin Belousov 	if ((res = poll(&pfd, 1, 0)) < 0)
1865861f966SKonstantin Belousov 		err(1, "poll");
187*42992a3aSKonstantin Belousov 	report(num++, "6", POLLIN | POLLHUP, pfd.revents, res, 1);
1885861f966SKonstantin Belousov 	if (read(fd, buf, sizeof buf) != 1)
1895861f966SKonstantin Belousov 		err(1, "read");
190*42992a3aSKonstantin Belousov 	if ((res = poll(&pfd, 1, 0)) < 0)
1915861f966SKonstantin Belousov 		err(1, "poll");
192*42992a3aSKonstantin Belousov 	report(num++, "6a", POLLHUP, pfd.revents, res, 1);
1935861f966SKonstantin Belousov 	if (filetype == FT_FIFO) {
1945861f966SKonstantin Belousov 		/*
1955861f966SKonstantin Belousov 		 * Check that POLLHUP is sticky for a new reader and for
1965861f966SKonstantin Belousov 		 * the old reader.
1975861f966SKonstantin Belousov 		 */
1985861f966SKonstantin Belousov 		fd2 = open(FIFONAME, O_RDONLY | O_NONBLOCK);
1995861f966SKonstantin Belousov 		if (fd2 < 0)
2005861f966SKonstantin Belousov 			err(1, "open for read");
2015861f966SKonstantin Belousov 		pfd.fd = fd2;
202*42992a3aSKonstantin Belousov 		if ((res = poll(&pfd, 1, 0)) < 0)
2035861f966SKonstantin Belousov 			err(1, "poll");
204*42992a3aSKonstantin Belousov 		report(num++, "6b", POLLHUP, pfd.revents, res, 1);
2055861f966SKonstantin Belousov 		pfd.fd = fd;
206*42992a3aSKonstantin Belousov 		if ((res = poll(&pfd, 1, 0)) < 0)
2075861f966SKonstantin Belousov 			err(1, "poll");
208*42992a3aSKonstantin Belousov 		report(num++, "6c", POLLHUP, pfd.revents, res, 1);
2095861f966SKonstantin Belousov 		close(fd2);
210*42992a3aSKonstantin Belousov 		if ((res = poll(&pfd, 1, 0)) < 0)
2115861f966SKonstantin Belousov 			err(1, "poll");
212*42992a3aSKonstantin Belousov 		report(num++, "6d", POLLHUP, pfd.revents, res, 1);
2135861f966SKonstantin Belousov 	}
2145861f966SKonstantin Belousov 	close(fd);
2155861f966SKonstantin Belousov 	kill(ppid, SIGUSR1);
2165861f966SKonstantin Belousov 
2175861f966SKonstantin Belousov 	exit(0);
2185861f966SKonstantin Belousov }
2195861f966SKonstantin Belousov 
2205861f966SKonstantin Belousov static void
2215861f966SKonstantin Belousov parent(int fd)
2225861f966SKonstantin Belousov {
2235861f966SKonstantin Belousov 	usleep(1);
2245861f966SKonstantin Belousov 	while (state != 1)
2255861f966SKonstantin Belousov 		;
2265861f966SKonstantin Belousov 	if (filetype == FT_FIFO) {
2275861f966SKonstantin Belousov 		fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
2285861f966SKonstantin Belousov 		if (fd < 0)
2295861f966SKonstantin Belousov 			err(1, "open for write");
2305861f966SKonstantin Belousov 	}
2315861f966SKonstantin Belousov 	kill(cpid, SIGUSR1);
2325861f966SKonstantin Belousov 
2335861f966SKonstantin Belousov 	usleep(1);
2345861f966SKonstantin Belousov 	while (state != 2)
2355861f966SKonstantin Belousov 		;
2365861f966SKonstantin Belousov 	if (write(fd, "", 1) != 1)
2375861f966SKonstantin Belousov 		err(1, "write");
2385861f966SKonstantin Belousov 	kill(cpid, SIGUSR1);
2395861f966SKonstantin Belousov 
2405861f966SKonstantin Belousov 	usleep(1);
2415861f966SKonstantin Belousov 	while (state != 3)
2425861f966SKonstantin Belousov 		;
2435861f966SKonstantin Belousov 	if (close(fd) != 0)
2445861f966SKonstantin Belousov 		err(1, "close for write");
2455861f966SKonstantin Belousov 	kill(cpid, SIGUSR1);
2465861f966SKonstantin Belousov 
2475861f966SKonstantin Belousov 	usleep(1);
2485861f966SKonstantin Belousov 	while (state != 4)
2495861f966SKonstantin Belousov 		;
2505861f966SKonstantin Belousov 	if (filetype != FT_FIFO)
2515861f966SKonstantin Belousov 		return;
2525861f966SKonstantin Belousov 	fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
2535861f966SKonstantin Belousov 	if (fd < 0)
2545861f966SKonstantin Belousov 		err(1, "open for write");
2555861f966SKonstantin Belousov 	kill(cpid, SIGUSR1);
2565861f966SKonstantin Belousov 
2575861f966SKonstantin Belousov 	usleep(1);
2585861f966SKonstantin Belousov 	while (state != 5)
2595861f966SKonstantin Belousov 		;
2605861f966SKonstantin Belousov 	if (write(fd, "", 1) != 1)
2615861f966SKonstantin Belousov 		err(1, "write");
2625861f966SKonstantin Belousov 	kill(cpid, SIGUSR1);
2635861f966SKonstantin Belousov 
2645861f966SKonstantin Belousov 	usleep(1);
2655861f966SKonstantin Belousov 	while (state != 6)
2665861f966SKonstantin Belousov 		;
2675861f966SKonstantin Belousov 	if (close(fd) != 0)
2685861f966SKonstantin Belousov 		err(1, "close for write");
2695861f966SKonstantin Belousov 	kill(cpid, SIGUSR1);
2705861f966SKonstantin Belousov 
2715861f966SKonstantin Belousov 	usleep(1);
2725861f966SKonstantin Belousov 	while (state != 7)
2735861f966SKonstantin Belousov 		;
2745861f966SKonstantin Belousov }
2755861f966SKonstantin Belousov 
2765861f966SKonstantin Belousov int
2775861f966SKonstantin Belousov main(void)
2785861f966SKonstantin Belousov {
2795861f966SKonstantin Belousov 	int fd[2], num;
2805861f966SKonstantin Belousov 
2815861f966SKonstantin Belousov 	num = 1;
2825861f966SKonstantin Belousov 	printf("1..20\n");
2835861f966SKonstantin Belousov 	fflush(stdout);
2845861f966SKonstantin Belousov 	signal(SIGUSR1, catch);
2855861f966SKonstantin Belousov 	ppid = getpid();
2865861f966SKonstantin Belousov 	for (filetype = 0; filetype < FT_END; filetype++) {
2875861f966SKonstantin Belousov 		switch (filetype) {
2885861f966SKonstantin Belousov 		case FT_FIFO:
2895861f966SKonstantin Belousov 			if (mkfifo(FIFONAME, 0666) != 0)
2905861f966SKonstantin Belousov 				err(1, "mkfifo");
2915861f966SKonstantin Belousov 			fd[0] = -1;
2925861f966SKonstantin Belousov 			fd[1] = -1;
2935861f966SKonstantin Belousov 			break;
2945861f966SKonstantin Belousov 		case FT_SOCKETPAIR:
2955861f966SKonstantin Belousov 			if (socketpair(AF_UNIX, SOCK_STREAM, AF_UNSPEC,
2965861f966SKonstantin Belousov 			    fd) != 0)
2975861f966SKonstantin Belousov 				err(1, "socketpair");
2985861f966SKonstantin Belousov 			break;
2995861f966SKonstantin Belousov 		case FT_PIPE:
3005861f966SKonstantin Belousov 			if (pipe(fd) != 0)
3015861f966SKonstantin Belousov 				err(1, "pipe");
3025861f966SKonstantin Belousov 			break;
3035861f966SKonstantin Belousov 		}
3045861f966SKonstantin Belousov 		state = 0;
3055861f966SKonstantin Belousov 		switch (cpid = fork()) {
3065861f966SKonstantin Belousov 		case -1:
3075861f966SKonstantin Belousov 			err(1, "fork");
3085861f966SKonstantin Belousov 		case 0:
3095861f966SKonstantin Belousov 			(void)close(fd[1]);
3105861f966SKonstantin Belousov 			child(fd[0], num);
3115861f966SKonstantin Belousov 			break;
3125861f966SKonstantin Belousov 		default:
3135861f966SKonstantin Belousov 			(void)close(fd[0]);
3145861f966SKonstantin Belousov 			parent(fd[1]);
3155861f966SKonstantin Belousov 			break;
3165861f966SKonstantin Belousov 		}
3175861f966SKonstantin Belousov 		num += filetype == FT_FIFO ? 12 : 4;
3185861f966SKonstantin Belousov 	}
3195861f966SKonstantin Belousov 	(void)unlink(FIFONAME);
3205861f966SKonstantin Belousov 	return (0);
3215861f966SKonstantin Belousov }
322