1 2 #include <sys/poll.h> 3 #include <sys/socket.h> 4 #include <sys/stat.h> 5 6 #include <err.h> 7 #include <fcntl.h> 8 #include <signal.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <unistd.h> 12 13 #define FIFONAME "fifo.tmp" 14 #define FT_END 3 15 #define FT_FIFO 2 16 #define FT_PIPE 0 17 #define FT_SOCKETPAIR 1 18 19 static int filetype; 20 21 static const char * 22 decode_events(int events) 23 { 24 char *ncresult; 25 const char *result; 26 27 switch (events) { 28 case POLLIN: 29 result = "POLLIN"; 30 break; 31 case POLLHUP: 32 result = "POLLHUP"; 33 break; 34 case POLLIN | POLLHUP: 35 result = "POLLIN | POLLHUP"; 36 break; 37 default: 38 asprintf(&ncresult, "%#x", events); 39 result = ncresult; 40 break; 41 } 42 return (result); 43 } 44 45 static void 46 report_state(const char *state) 47 { 48 49 printf(" %s state %s: ", 50 filetype == FT_PIPE ? "Pipe" : 51 filetype == FT_SOCKETPAIR ? "Sock" : "FIFO", 52 state); 53 } 54 55 static void 56 report(int num, const char *state, int expected, int got, int res, 57 int res_expected) 58 { 59 60 if (res != res_expected) { 61 printf("not ok %-2d", num); 62 report_state(state); 63 printf("poll result %d expected %d. ", 64 res, res_expected); 65 } else { 66 if (expected == got) 67 printf("ok %-2d ", num); 68 else 69 printf("not ok %-2d", num); 70 report_state(state); 71 } 72 printf("expected %s; got %s\n", decode_events(expected), 73 decode_events(got)); 74 fflush(stdout); 75 } 76 77 static pid_t cpid; 78 static pid_t ppid; 79 static volatile sig_atomic_t state; 80 81 static void 82 catch(int sig __unused) 83 { 84 85 state++; 86 } 87 88 static void 89 child(int fd, int num) 90 { 91 struct pollfd pfd; 92 int fd2, res; 93 char buf[256]; 94 95 if (filetype == FT_FIFO) { 96 fd = open(FIFONAME, O_RDONLY | O_NONBLOCK); 97 if (fd < 0) 98 err(1, "open for read"); 99 } 100 pfd.fd = fd; 101 pfd.events = POLLIN; 102 103 if (filetype == FT_FIFO) { 104 if ((res = poll(&pfd, 1, 0)) < 0) 105 err(1, "poll"); 106 report(num++, "0", 0, pfd.revents, res, 0); 107 } 108 kill(ppid, SIGUSR1); 109 110 usleep(1); 111 while (state != 1) 112 ; 113 if (filetype != FT_FIFO) { 114 /* 115 * The connection cannot be reestablished. Use the code that 116 * delays the read until after the writer disconnects since 117 * that case is more interesting. 118 */ 119 state = 4; 120 goto state4; 121 } 122 if ((res = poll(&pfd, 1, 0)) < 0) 123 err(1, "poll"); 124 report(num++, "1", 0, pfd.revents, res, 0); 125 kill(ppid, SIGUSR1); 126 127 usleep(1); 128 while (state != 2) 129 ; 130 if ((res = poll(&pfd, 1, 0)) < 0) 131 err(1, "poll"); 132 report(num++, "2", POLLIN, pfd.revents, res, 1); 133 if (read(fd, buf, sizeof buf) != 1) 134 err(1, "read"); 135 if ((res = poll(&pfd, 1, 0)) < 0) 136 err(1, "poll"); 137 report(num++, "2a", 0, pfd.revents, res, 0); 138 kill(ppid, SIGUSR1); 139 140 usleep(1); 141 while (state != 3) 142 ; 143 if ((res = poll(&pfd, 1, 0)) < 0) 144 err(1, "poll"); 145 report(num++, "3", POLLHUP, pfd.revents, res, 1); 146 kill(ppid, SIGUSR1); 147 148 /* 149 * Now we expect a new writer, and a new connection too since 150 * we read all the data. The only new point is that we didn't 151 * start quite from scratch since the read fd is not new. Check 152 * startup state as above, but don't do the read as above. 153 */ 154 usleep(1); 155 while (state != 4) 156 ; 157 state4: 158 if ((res = poll(&pfd, 1, 0)) < 0) 159 err(1, "poll"); 160 report(num++, "4", 0, pfd.revents, res, 0); 161 kill(ppid, SIGUSR1); 162 163 usleep(1); 164 while (state != 5) 165 ; 166 if ((res = poll(&pfd, 1, 0)) < 0) 167 err(1, "poll"); 168 report(num++, "5", POLLIN, pfd.revents, res, 1); 169 kill(ppid, SIGUSR1); 170 171 usleep(1); 172 while (state != 6) 173 ; 174 /* 175 * Now we have no writer, but should still have data from the old 176 * writer. Check that we have both a data-readable condition and a 177 * hangup condition, and that the data can be read in the usual way. 178 * Since Linux does this, programs must not quit reading when they 179 * see POLLHUP; they must see POLLHUP without POLLIN (or another 180 * input condition) before they decide that there is EOF. gdb-6.1.1 181 * is an example of a broken program that quits on POLLHUP only -- 182 * see its event-loop.c. 183 */ 184 if ((res = poll(&pfd, 1, 0)) < 0) 185 err(1, "poll"); 186 report(num++, "6", POLLIN | POLLHUP, pfd.revents, res, 1); 187 if (read(fd, buf, sizeof buf) != 1) 188 err(1, "read"); 189 if ((res = poll(&pfd, 1, 0)) < 0) 190 err(1, "poll"); 191 report(num++, "6a", POLLHUP, pfd.revents, res, 1); 192 if (filetype == FT_FIFO) { 193 /* 194 * Check that POLLHUP is sticky for a new reader and for 195 * the old reader. 196 */ 197 fd2 = open(FIFONAME, O_RDONLY | O_NONBLOCK); 198 if (fd2 < 0) 199 err(1, "open for read"); 200 pfd.fd = fd2; 201 if ((res = poll(&pfd, 1, 0)) < 0) 202 err(1, "poll"); 203 report(num++, "6b", POLLHUP, pfd.revents, res, 1); 204 pfd.fd = fd; 205 if ((res = poll(&pfd, 1, 0)) < 0) 206 err(1, "poll"); 207 report(num++, "6c", POLLHUP, pfd.revents, res, 1); 208 close(fd2); 209 if ((res = poll(&pfd, 1, 0)) < 0) 210 err(1, "poll"); 211 report(num++, "6d", POLLHUP, pfd.revents, res, 1); 212 } 213 close(fd); 214 kill(ppid, SIGUSR1); 215 216 exit(0); 217 } 218 219 static void 220 parent(int fd) 221 { 222 usleep(1); 223 while (state != 1) 224 ; 225 if (filetype == FT_FIFO) { 226 fd = open(FIFONAME, O_WRONLY | O_NONBLOCK); 227 if (fd < 0) 228 err(1, "open for write"); 229 } 230 kill(cpid, SIGUSR1); 231 232 usleep(1); 233 while (state != 2) 234 ; 235 if (write(fd, "", 1) != 1) 236 err(1, "write"); 237 kill(cpid, SIGUSR1); 238 239 usleep(1); 240 while (state != 3) 241 ; 242 if (close(fd) != 0) 243 err(1, "close for write"); 244 kill(cpid, SIGUSR1); 245 246 usleep(1); 247 while (state != 4) 248 ; 249 if (filetype != FT_FIFO) 250 return; 251 fd = open(FIFONAME, O_WRONLY | O_NONBLOCK); 252 if (fd < 0) 253 err(1, "open for write"); 254 kill(cpid, SIGUSR1); 255 256 usleep(1); 257 while (state != 5) 258 ; 259 if (write(fd, "", 1) != 1) 260 err(1, "write"); 261 kill(cpid, SIGUSR1); 262 263 usleep(1); 264 while (state != 6) 265 ; 266 if (close(fd) != 0) 267 err(1, "close for write"); 268 kill(cpid, SIGUSR1); 269 270 usleep(1); 271 while (state != 7) 272 ; 273 } 274 275 int 276 main(void) 277 { 278 int fd[2], num; 279 280 num = 1; 281 printf("1..20\n"); 282 fflush(stdout); 283 signal(SIGUSR1, catch); 284 ppid = getpid(); 285 for (filetype = 0; filetype < FT_END; filetype++) { 286 switch (filetype) { 287 case FT_FIFO: 288 if (mkfifo(FIFONAME, 0666) != 0) 289 err(1, "mkfifo"); 290 fd[0] = -1; 291 fd[1] = -1; 292 break; 293 case FT_SOCKETPAIR: 294 if (socketpair(AF_UNIX, SOCK_STREAM, AF_UNSPEC, 295 fd) != 0) 296 err(1, "socketpair"); 297 break; 298 case FT_PIPE: 299 if (pipe(fd) != 0) 300 err(1, "pipe"); 301 break; 302 } 303 state = 0; 304 switch (cpid = fork()) { 305 case -1: 306 err(1, "fork"); 307 case 0: 308 (void)close(fd[1]); 309 child(fd[0], num); 310 break; 311 default: 312 (void)close(fd[0]); 313 parent(fd[1]); 314 break; 315 } 316 num += filetype == FT_FIFO ? 12 : 4; 317 } 318 (void)unlink(FIFONAME); 319 return (0); 320 } 321