3 #include <sys/socket.h>
4 #include <sys/select.h>
14 #define FIFONAME "fifo.tmp"
18 #define FT_SOCKETPAIR 1
20 #define SETUP(fd, rfds, tv) do { \
22 FD_SET((fd), &(rfds)); \
30 decode_events(int events)
32 return (events ? "set" : "clear");
36 report(int num, const char *state, int expected, int got)
38 if (!expected == !got)
39 printf("ok %-2d ", num);
41 printf("not ok %-2d", num);
42 printf(" %s state %s: expected %s; got %s\n",
43 filetype == FT_PIPE ? "Pipe" :
44 filetype == FT_SOCKETPAIR ? "Sock" : "FIFO",
45 state, decode_events(expected), decode_events(got));
51 static volatile sig_atomic_t state;
60 child(int fd, int num)
67 if (filetype == FT_FIFO) {
68 fd = open(FIFONAME, O_RDONLY | O_NONBLOCK);
70 err(1, "open for read");
73 errx(1, "fd = %d too large for select()", fd);
75 if (filetype == FT_FIFO) {
77 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
80 * This state (a reader for which there has never been a
81 * writer) is reported quite differently for select() than
82 * for poll(). select() must see a ready-to-read descriptor
83 * since read() will see EOF and not block; it cannot
84 * distinguish this state from the one of a reader for which
85 * there has been a writer but all writers have gone away
86 * and all data has been read. poll() and distinguish these
87 * states by returning POLLHUP only for the latter; it does
88 * this, although this makes it inconsistent with the
89 * blockability of read() in the former.
91 report(num++, "0", 1, FD_ISSET(fd, &rfds));
98 if (filetype != FT_FIFO) {
100 * The connection cannot be reestablished. Use the code that
101 * delays the read until after the writer disconnects since
102 * that case is more interesting.
108 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
110 report(num++, "1", 0, FD_ISSET(fd, &rfds));
117 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
119 report(num++, "2", 1, FD_ISSET(fd, &rfds));
120 if (read(fd, buf, sizeof buf) != 1)
123 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
125 report(num++, "2a", 0, FD_ISSET(fd, &rfds));
132 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
134 report(num++, "3", 1, FD_ISSET(fd, &rfds));
138 * Now we expect a new writer, and a new connection too since
139 * we read all the data. The only new point is that we didn't
140 * start quite from scratch since the read fd is not new. Check
141 * startup state as above, but don't do the read as above.
148 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
150 report(num++, "4", 0, FD_ISSET(fd, &rfds));
157 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
159 report(num++, "5", 1, FD_ISSET(fd, &rfds));
166 * Now we have no writer, but should still have data from the old
167 * writer. Check that we have a data-readable condition, and that
168 * the data can be read in the usual way.
171 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
173 report(num++, "6", 1, FD_ISSET(fd, &rfds));
174 if (read(fd, buf, sizeof buf) != 1)
177 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
179 report(num++, "6a", 1, FD_ISSET(fd, &rfds));
180 if (filetype == FT_FIFO) {
182 * Check that the readable-data condition is sticky for a
183 * new reader and for the old reader. We really only have
184 * a hangup condition, but select() can only see this as
185 * a readable-data condition for null data. select()
186 * cannot distinguish this state from the initial state
187 * where there is a reader but has never been a writer, so
188 * the following tests (to follow the pattern in pipepoll.c)
189 * essentially test state 0 again.
191 fd2 = open(FIFONAME, O_RDONLY | O_NONBLOCK);
193 err(1, "open for read");
197 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
199 report(num++, "6b", 1, FD_ISSET(fd, &rfds));
202 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
204 report(num++, "6c", 1, FD_ISSET(fd, &rfds));
207 if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
209 report(num++, "6d", 1, FD_ISSET(fd, &rfds));
223 if (filetype == FT_FIFO) {
224 fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
226 err(1, "open for write");
233 if (write(fd, "", 1) != 1)
241 err(1, "close for write");
247 if (filetype != FT_FIFO)
249 fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
251 err(1, "open for write");
257 if (write(fd, "", 1) != 1)
265 err(1, "close for write");
281 signal(SIGUSR1, catch);
283 for (filetype = 0; filetype < FT_END; filetype++) {
286 if (mkfifo(FIFONAME, 0666) != 0)
292 if (socketpair(AF_UNIX, SOCK_STREAM, AF_UNSPEC,
294 err(1, "socketpair");
302 switch (cpid = fork()) {
314 num += filetype == FT_FIFO ? 12 : 4;
316 (void)unlink(FIFONAME);