15861f966SKonstantin Belousov
25861f966SKonstantin Belousov #include <sys/poll.h>
35861f966SKonstantin Belousov #include <sys/socket.h>
45861f966SKonstantin Belousov #include <sys/stat.h>
55861f966SKonstantin Belousov
65861f966SKonstantin Belousov #include <err.h>
75861f966SKonstantin Belousov #include <fcntl.h>
85861f966SKonstantin Belousov #include <signal.h>
95861f966SKonstantin Belousov #include <stdio.h>
105861f966SKonstantin Belousov #include <stdlib.h>
115861f966SKonstantin Belousov #include <unistd.h>
125861f966SKonstantin Belousov
135861f966SKonstantin Belousov #define FIFONAME "fifo.tmp"
145861f966SKonstantin Belousov #define FT_END 3
155861f966SKonstantin Belousov #define FT_FIFO 2
165861f966SKonstantin Belousov #define FT_PIPE 0
175861f966SKonstantin Belousov #define FT_SOCKETPAIR 1
185861f966SKonstantin Belousov
195861f966SKonstantin Belousov static int filetype;
205861f966SKonstantin Belousov
215861f966SKonstantin Belousov static const char *
decode_events(int events)225861f966SKonstantin Belousov decode_events(int events)
235861f966SKonstantin Belousov {
245861f966SKonstantin Belousov char *ncresult;
255861f966SKonstantin Belousov const char *result;
265861f966SKonstantin Belousov
275861f966SKonstantin Belousov switch (events) {
285861f966SKonstantin Belousov case POLLIN:
295861f966SKonstantin Belousov result = "POLLIN";
305861f966SKonstantin Belousov break;
315861f966SKonstantin Belousov case POLLHUP:
325861f966SKonstantin Belousov result = "POLLHUP";
335861f966SKonstantin Belousov break;
345861f966SKonstantin Belousov case POLLIN | POLLHUP:
355861f966SKonstantin Belousov result = "POLLIN | POLLHUP";
365861f966SKonstantin Belousov break;
375861f966SKonstantin Belousov default:
385861f966SKonstantin Belousov asprintf(&ncresult, "%#x", events);
395861f966SKonstantin Belousov result = ncresult;
405861f966SKonstantin Belousov break;
415861f966SKonstantin Belousov }
425861f966SKonstantin Belousov return (result);
435861f966SKonstantin Belousov }
445861f966SKonstantin Belousov
455861f966SKonstantin Belousov static void
report_state(const char * state)46*42992a3aSKonstantin Belousov report_state(const char *state)
475861f966SKonstantin Belousov {
48*42992a3aSKonstantin Belousov
49*42992a3aSKonstantin Belousov printf(" %s state %s: ",
50*42992a3aSKonstantin Belousov filetype == FT_PIPE ? "Pipe" :
51*42992a3aSKonstantin Belousov filetype == FT_SOCKETPAIR ? "Sock" : "FIFO",
52*42992a3aSKonstantin Belousov state);
53*42992a3aSKonstantin Belousov }
54*42992a3aSKonstantin Belousov
55*42992a3aSKonstantin Belousov static void
report(int num,const char * state,int expected,int got,int res,int res_expected)56*42992a3aSKonstantin Belousov report(int num, const char *state, int expected, int got, int res,
57*42992a3aSKonstantin Belousov int res_expected)
58*42992a3aSKonstantin Belousov {
59*42992a3aSKonstantin Belousov
60*42992a3aSKonstantin Belousov if (res != res_expected) {
61*42992a3aSKonstantin Belousov printf("not ok %-2d", num);
62*42992a3aSKonstantin Belousov report_state(state);
63*42992a3aSKonstantin Belousov printf("poll result %d expected %d. ",
64*42992a3aSKonstantin Belousov res, res_expected);
65*42992a3aSKonstantin Belousov } else {
665861f966SKonstantin Belousov if (expected == got)
675861f966SKonstantin Belousov printf("ok %-2d ", num);
685861f966SKonstantin Belousov else
695861f966SKonstantin Belousov printf("not ok %-2d", num);
70*42992a3aSKonstantin Belousov report_state(state);
71*42992a3aSKonstantin Belousov }
72*42992a3aSKonstantin Belousov printf("expected %s; got %s\n", decode_events(expected),
73*42992a3aSKonstantin Belousov decode_events(got));
745861f966SKonstantin Belousov fflush(stdout);
755861f966SKonstantin Belousov }
765861f966SKonstantin Belousov
775861f966SKonstantin Belousov static pid_t cpid;
785861f966SKonstantin Belousov static pid_t ppid;
795861f966SKonstantin Belousov static volatile sig_atomic_t state;
805861f966SKonstantin Belousov
815861f966SKonstantin Belousov static void
catch(int sig __unused)82*42992a3aSKonstantin Belousov catch(int sig __unused)
835861f966SKonstantin Belousov {
84*42992a3aSKonstantin Belousov
855861f966SKonstantin Belousov state++;
865861f966SKonstantin Belousov }
875861f966SKonstantin Belousov
885861f966SKonstantin Belousov static void
child(int fd,int num)895861f966SKonstantin Belousov child(int fd, int num)
905861f966SKonstantin Belousov {
915861f966SKonstantin Belousov struct pollfd pfd;
92*42992a3aSKonstantin Belousov int fd2, res;
935861f966SKonstantin Belousov char buf[256];
945861f966SKonstantin Belousov
955861f966SKonstantin Belousov if (filetype == FT_FIFO) {
965861f966SKonstantin Belousov fd = open(FIFONAME, O_RDONLY | O_NONBLOCK);
975861f966SKonstantin Belousov if (fd < 0)
985861f966SKonstantin Belousov err(1, "open for read");
995861f966SKonstantin Belousov }
1005861f966SKonstantin Belousov pfd.fd = fd;
1015861f966SKonstantin Belousov pfd.events = POLLIN;
1025861f966SKonstantin Belousov
1035861f966SKonstantin Belousov if (filetype == FT_FIFO) {
104*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
1055861f966SKonstantin Belousov err(1, "poll");
106*42992a3aSKonstantin Belousov report(num++, "0", 0, pfd.revents, res, 0);
1075861f966SKonstantin Belousov }
1085861f966SKonstantin Belousov kill(ppid, SIGUSR1);
1095861f966SKonstantin Belousov
1105861f966SKonstantin Belousov usleep(1);
1115861f966SKonstantin Belousov while (state != 1)
1125861f966SKonstantin Belousov ;
1135861f966SKonstantin Belousov if (filetype != FT_FIFO) {
1145861f966SKonstantin Belousov /*
1155861f966SKonstantin Belousov * The connection cannot be reestablished. Use the code that
1165861f966SKonstantin Belousov * delays the read until after the writer disconnects since
1175861f966SKonstantin Belousov * that case is more interesting.
1185861f966SKonstantin Belousov */
1195861f966SKonstantin Belousov state = 4;
1205861f966SKonstantin Belousov goto state4;
1215861f966SKonstantin Belousov }
122*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
1235861f966SKonstantin Belousov err(1, "poll");
124*42992a3aSKonstantin Belousov report(num++, "1", 0, pfd.revents, res, 0);
1255861f966SKonstantin Belousov kill(ppid, SIGUSR1);
1265861f966SKonstantin Belousov
1275861f966SKonstantin Belousov usleep(1);
1285861f966SKonstantin Belousov while (state != 2)
1295861f966SKonstantin Belousov ;
130*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
1315861f966SKonstantin Belousov err(1, "poll");
132*42992a3aSKonstantin Belousov report(num++, "2", POLLIN, pfd.revents, res, 1);
1335861f966SKonstantin Belousov if (read(fd, buf, sizeof buf) != 1)
1345861f966SKonstantin Belousov err(1, "read");
135*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
1365861f966SKonstantin Belousov err(1, "poll");
137*42992a3aSKonstantin Belousov report(num++, "2a", 0, pfd.revents, res, 0);
1385861f966SKonstantin Belousov kill(ppid, SIGUSR1);
1395861f966SKonstantin Belousov
1405861f966SKonstantin Belousov usleep(1);
1415861f966SKonstantin Belousov while (state != 3)
1425861f966SKonstantin Belousov ;
143*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
1445861f966SKonstantin Belousov err(1, "poll");
145*42992a3aSKonstantin Belousov report(num++, "3", POLLHUP, pfd.revents, res, 1);
1465861f966SKonstantin Belousov kill(ppid, SIGUSR1);
1475861f966SKonstantin Belousov
1485861f966SKonstantin Belousov /*
1495861f966SKonstantin Belousov * Now we expect a new writer, and a new connection too since
1505861f966SKonstantin Belousov * we read all the data. The only new point is that we didn't
1515861f966SKonstantin Belousov * start quite from scratch since the read fd is not new. Check
1525861f966SKonstantin Belousov * startup state as above, but don't do the read as above.
1535861f966SKonstantin Belousov */
1545861f966SKonstantin Belousov usleep(1);
1555861f966SKonstantin Belousov while (state != 4)
1565861f966SKonstantin Belousov ;
1575861f966SKonstantin Belousov state4:
158*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
1595861f966SKonstantin Belousov err(1, "poll");
160*42992a3aSKonstantin Belousov report(num++, "4", 0, pfd.revents, res, 0);
1615861f966SKonstantin Belousov kill(ppid, SIGUSR1);
1625861f966SKonstantin Belousov
1635861f966SKonstantin Belousov usleep(1);
1645861f966SKonstantin Belousov while (state != 5)
1655861f966SKonstantin Belousov ;
166*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
1675861f966SKonstantin Belousov err(1, "poll");
168*42992a3aSKonstantin Belousov report(num++, "5", POLLIN, pfd.revents, res, 1);
1695861f966SKonstantin Belousov kill(ppid, SIGUSR1);
1705861f966SKonstantin Belousov
1715861f966SKonstantin Belousov usleep(1);
1725861f966SKonstantin Belousov while (state != 6)
1735861f966SKonstantin Belousov ;
1745861f966SKonstantin Belousov /*
1755861f966SKonstantin Belousov * Now we have no writer, but should still have data from the old
1765861f966SKonstantin Belousov * writer. Check that we have both a data-readable condition and a
1775861f966SKonstantin Belousov * hangup condition, and that the data can be read in the usual way.
1785861f966SKonstantin Belousov * Since Linux does this, programs must not quit reading when they
1795861f966SKonstantin Belousov * see POLLHUP; they must see POLLHUP without POLLIN (or another
1805861f966SKonstantin Belousov * input condition) before they decide that there is EOF. gdb-6.1.1
1815861f966SKonstantin Belousov * is an example of a broken program that quits on POLLHUP only --
1825861f966SKonstantin Belousov * see its event-loop.c.
1835861f966SKonstantin Belousov */
184*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
1855861f966SKonstantin Belousov err(1, "poll");
186*42992a3aSKonstantin Belousov report(num++, "6", POLLIN | POLLHUP, pfd.revents, res, 1);
1875861f966SKonstantin Belousov if (read(fd, buf, sizeof buf) != 1)
1885861f966SKonstantin Belousov err(1, "read");
189*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
1905861f966SKonstantin Belousov err(1, "poll");
191*42992a3aSKonstantin Belousov report(num++, "6a", POLLHUP, pfd.revents, res, 1);
1925861f966SKonstantin Belousov if (filetype == FT_FIFO) {
1935861f966SKonstantin Belousov /*
1945861f966SKonstantin Belousov * Check that POLLHUP is sticky for a new reader and for
1955861f966SKonstantin Belousov * the old reader.
1965861f966SKonstantin Belousov */
1975861f966SKonstantin Belousov fd2 = open(FIFONAME, O_RDONLY | O_NONBLOCK);
1985861f966SKonstantin Belousov if (fd2 < 0)
1995861f966SKonstantin Belousov err(1, "open for read");
2005861f966SKonstantin Belousov pfd.fd = fd2;
201*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
2025861f966SKonstantin Belousov err(1, "poll");
203*42992a3aSKonstantin Belousov report(num++, "6b", POLLHUP, pfd.revents, res, 1);
2045861f966SKonstantin Belousov pfd.fd = fd;
205*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
2065861f966SKonstantin Belousov err(1, "poll");
207*42992a3aSKonstantin Belousov report(num++, "6c", POLLHUP, pfd.revents, res, 1);
2085861f966SKonstantin Belousov close(fd2);
209*42992a3aSKonstantin Belousov if ((res = poll(&pfd, 1, 0)) < 0)
2105861f966SKonstantin Belousov err(1, "poll");
211*42992a3aSKonstantin Belousov report(num++, "6d", POLLHUP, pfd.revents, res, 1);
2125861f966SKonstantin Belousov }
2135861f966SKonstantin Belousov close(fd);
2145861f966SKonstantin Belousov kill(ppid, SIGUSR1);
2155861f966SKonstantin Belousov
2165861f966SKonstantin Belousov exit(0);
2175861f966SKonstantin Belousov }
2185861f966SKonstantin Belousov
2195861f966SKonstantin Belousov static void
parent(int fd)2205861f966SKonstantin Belousov parent(int fd)
2215861f966SKonstantin Belousov {
2225861f966SKonstantin Belousov usleep(1);
2235861f966SKonstantin Belousov while (state != 1)
2245861f966SKonstantin Belousov ;
2255861f966SKonstantin Belousov if (filetype == FT_FIFO) {
2265861f966SKonstantin Belousov fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
2275861f966SKonstantin Belousov if (fd < 0)
2285861f966SKonstantin Belousov err(1, "open for write");
2295861f966SKonstantin Belousov }
2305861f966SKonstantin Belousov kill(cpid, SIGUSR1);
2315861f966SKonstantin Belousov
2325861f966SKonstantin Belousov usleep(1);
2335861f966SKonstantin Belousov while (state != 2)
2345861f966SKonstantin Belousov ;
2355861f966SKonstantin Belousov if (write(fd, "", 1) != 1)
2365861f966SKonstantin Belousov err(1, "write");
2375861f966SKonstantin Belousov kill(cpid, SIGUSR1);
2385861f966SKonstantin Belousov
2395861f966SKonstantin Belousov usleep(1);
2405861f966SKonstantin Belousov while (state != 3)
2415861f966SKonstantin Belousov ;
2425861f966SKonstantin Belousov if (close(fd) != 0)
2435861f966SKonstantin Belousov err(1, "close for write");
2445861f966SKonstantin Belousov kill(cpid, SIGUSR1);
2455861f966SKonstantin Belousov
2465861f966SKonstantin Belousov usleep(1);
2475861f966SKonstantin Belousov while (state != 4)
2485861f966SKonstantin Belousov ;
2495861f966SKonstantin Belousov if (filetype != FT_FIFO)
2505861f966SKonstantin Belousov return;
2515861f966SKonstantin Belousov fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
2525861f966SKonstantin Belousov if (fd < 0)
2535861f966SKonstantin Belousov err(1, "open for write");
2545861f966SKonstantin Belousov kill(cpid, SIGUSR1);
2555861f966SKonstantin Belousov
2565861f966SKonstantin Belousov usleep(1);
2575861f966SKonstantin Belousov while (state != 5)
2585861f966SKonstantin Belousov ;
2595861f966SKonstantin Belousov if (write(fd, "", 1) != 1)
2605861f966SKonstantin Belousov err(1, "write");
2615861f966SKonstantin Belousov kill(cpid, SIGUSR1);
2625861f966SKonstantin Belousov
2635861f966SKonstantin Belousov usleep(1);
2645861f966SKonstantin Belousov while (state != 6)
2655861f966SKonstantin Belousov ;
2665861f966SKonstantin Belousov if (close(fd) != 0)
2675861f966SKonstantin Belousov err(1, "close for write");
2685861f966SKonstantin Belousov kill(cpid, SIGUSR1);
2695861f966SKonstantin Belousov
2705861f966SKonstantin Belousov usleep(1);
2715861f966SKonstantin Belousov while (state != 7)
2725861f966SKonstantin Belousov ;
2735861f966SKonstantin Belousov }
2745861f966SKonstantin Belousov
2755861f966SKonstantin Belousov int
main(void)2765861f966SKonstantin Belousov main(void)
2775861f966SKonstantin Belousov {
2785861f966SKonstantin Belousov int fd[2], num;
2795861f966SKonstantin Belousov
2805861f966SKonstantin Belousov num = 1;
2815861f966SKonstantin Belousov printf("1..20\n");
2825861f966SKonstantin Belousov fflush(stdout);
2835861f966SKonstantin Belousov signal(SIGUSR1, catch);
2845861f966SKonstantin Belousov ppid = getpid();
2855861f966SKonstantin Belousov for (filetype = 0; filetype < FT_END; filetype++) {
2865861f966SKonstantin Belousov switch (filetype) {
2875861f966SKonstantin Belousov case FT_FIFO:
2885861f966SKonstantin Belousov if (mkfifo(FIFONAME, 0666) != 0)
2895861f966SKonstantin Belousov err(1, "mkfifo");
2905861f966SKonstantin Belousov fd[0] = -1;
2915861f966SKonstantin Belousov fd[1] = -1;
2925861f966SKonstantin Belousov break;
2935861f966SKonstantin Belousov case FT_SOCKETPAIR:
2945861f966SKonstantin Belousov if (socketpair(AF_UNIX, SOCK_STREAM, AF_UNSPEC,
2955861f966SKonstantin Belousov fd) != 0)
2965861f966SKonstantin Belousov err(1, "socketpair");
2975861f966SKonstantin Belousov break;
2985861f966SKonstantin Belousov case FT_PIPE:
2995861f966SKonstantin Belousov if (pipe(fd) != 0)
3005861f966SKonstantin Belousov err(1, "pipe");
3015861f966SKonstantin Belousov break;
3025861f966SKonstantin Belousov }
3035861f966SKonstantin Belousov state = 0;
3045861f966SKonstantin Belousov switch (cpid = fork()) {
3055861f966SKonstantin Belousov case -1:
3065861f966SKonstantin Belousov err(1, "fork");
3075861f966SKonstantin Belousov case 0:
3085861f966SKonstantin Belousov (void)close(fd[1]);
3095861f966SKonstantin Belousov child(fd[0], num);
3105861f966SKonstantin Belousov break;
3115861f966SKonstantin Belousov default:
3125861f966SKonstantin Belousov (void)close(fd[0]);
3135861f966SKonstantin Belousov parent(fd[1]);
3145861f966SKonstantin Belousov break;
3155861f966SKonstantin Belousov }
3165861f966SKonstantin Belousov num += filetype == FT_FIFO ? 12 : 4;
3175861f966SKonstantin Belousov }
3185861f966SKonstantin Belousov (void)unlink(FIFONAME);
3195861f966SKonstantin Belousov return (0);
3205861f966SKonstantin Belousov }
321