2 #include <sys/socket.h>
3 #include <sys/select.h>
13 #define FIFONAME "fifo.tmp"
17 #define FT_SOCKETPAIR 1
19 #define SETUP(fd, rfds, tv) do { \
21 FD_SET((fd), &(rfds)); \
29 decode_events(int events)
31 return (events ? "set" : "clear");
35 report(int num, const char *state, int expected, int got)
37 if (!expected == !got)
38 printf("ok %-2d ", num);
40 printf("not ok %-2d", num);
41 printf(" %s state %s: expected %s; got %s\n",
42 filetype == FT_PIPE ? "Pipe" :
43 filetype == FT_SOCKETPAIR ? "Sock" : "FIFO",
44 state, decode_events(expected), decode_events(got));
50 static volatile sig_atomic_t state;
59 child(int fd, int num)
66 if (filetype == FT_FIFO) {
67 fd = open(FIFONAME, O_RDONLY | O_NONBLOCK);
69 err(1, "open for read");
72 errx(1, "fd = %d too large for select()", fd);
74 if (filetype == FT_FIFO) {
76 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
79 * This state (a reader for which there has never been a
80 * writer) is reported quite differently for select() than
81 * for poll(). select() must see a ready-to-read descriptor
82 * since read() will see EOF and not block; it cannot
83 * distinguish this state from the one of a reader for which
84 * there has been a writer but all writers have gone away
85 * and all data has been read. poll() and distinguish these
86 * states by returning POLLHUP only for the latter; it does
87 * this, although this makes it inconsistent with the
88 * blockability of read() in the former.
90 report(num++, "0", 1, FD_ISSET(fd, &rfds));
97 if (filetype != FT_FIFO) {
99 * The connection cannot be reestablished. Use the code that
100 * delays the read until after the writer disconnects since
101 * that case is more interesting.
107 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
109 report(num++, "1", 0, FD_ISSET(fd, &rfds));
116 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
118 report(num++, "2", 1, FD_ISSET(fd, &rfds));
119 if (read(fd, buf, sizeof buf) != 1)
122 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
124 report(num++, "2a", 0, FD_ISSET(fd, &rfds));
131 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
133 report(num++, "3", 1, FD_ISSET(fd, &rfds));
137 * Now we expect a new writer, and a new connection too since
138 * we read all the data. The only new point is that we didn't
139 * start quite from scratch since the read fd is not new. Check
140 * startup state as above, but don't do the read as above.
147 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
149 report(num++, "4", 0, FD_ISSET(fd, &rfds));
156 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
158 report(num++, "5", 1, FD_ISSET(fd, &rfds));
165 * Now we have no writer, but should still have data from the old
166 * writer. Check that we have a data-readable condition, and that
167 * the data can be read in the usual way.
170 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
172 report(num++, "6", 1, FD_ISSET(fd, &rfds));
173 if (read(fd, buf, sizeof buf) != 1)
176 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
178 report(num++, "6a", 1, FD_ISSET(fd, &rfds));
179 if (filetype == FT_FIFO) {
181 * Check that the readable-data condition is sticky for a
182 * new reader and for the old reader. We really only have
183 * a hangup condition, but select() can only see this as
184 * a readable-data condition for null data. select()
185 * cannot distinguish this state from the initial state
186 * where there is a reader but has never been a writer, so
187 * the following tests (to follow the pattern in pipepoll.c)
188 * essentially test state 0 again.
190 fd2 = open(FIFONAME, O_RDONLY | O_NONBLOCK);
192 err(1, "open for read");
196 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
198 report(num++, "6b", 1, FD_ISSET(fd, &rfds));
201 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
203 report(num++, "6c", 1, FD_ISSET(fd, &rfds));
206 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
208 report(num++, "6d", 1, FD_ISSET(fd, &rfds));
222 if (filetype == FT_FIFO) {
223 fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
225 err(1, "open for write");
232 if (write(fd, "", 1) != 1)
240 err(1, "close for write");
246 if (filetype != FT_FIFO)
248 fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
250 err(1, "open for write");
256 if (write(fd, "", 1) != 1)
264 err(1, "close for write");
280 signal(SIGUSR1, catch);
282 for (filetype = 0; filetype < FT_END; filetype++) {
285 if (mkfifo(FIFONAME, 0666) != 0)
291 if (socketpair(AF_UNIX, SOCK_STREAM, AF_UNSPEC,
293 err(1, "socketpair");
301 switch (cpid = fork()) {
313 num += filetype == FT_FIFO ? 12 : 4;
315 (void)unlink(FIFONAME);