1 /* $FreeBSD$ */ 2 3 #include <sys/poll.h> 4 #include <sys/socket.h> 5 #include <sys/stat.h> 6 7 #include <err.h> 8 #include <fcntl.h> 9 #include <signal.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <unistd.h> 13 14 static const char * 15 decode_events(int events) 16 { 17 char *ncresult; 18 const char *result; 19 20 switch (events) { 21 case POLLIN: 22 result = "POLLIN"; 23 break; 24 case POLLOUT: 25 result = "POLLOUT"; 26 break; 27 case POLLIN | POLLOUT: 28 result = "POLLIN | POLLOUT"; 29 break; 30 case POLLHUP: 31 result = "POLLHUP"; 32 break; 33 case POLLIN | POLLHUP: 34 result = "POLLIN | POLLHUP"; 35 break; 36 case POLLOUT | POLLHUP: 37 result = "POLLOUT | POLLHUP"; 38 break; 39 case POLLIN | POLLOUT | POLLHUP: 40 result = "POLLIN | POLLOUT | POLLHUP"; 41 break; 42 default: 43 asprintf(&ncresult, "%#x", events); 44 result = ncresult; 45 break; 46 } 47 return (result); 48 } 49 50 static void 51 report(int num, const char *state, int expected, int got) 52 { 53 if (expected == got) 54 printf("ok %-2d ", num); 55 else 56 printf("not ok %-2d", num); 57 printf(" state %s: expected %s; got %s\n", 58 state, decode_events(expected), decode_events(got)); 59 fflush(stdout); 60 } 61 62 static int 63 set_nonblocking(int sck) 64 { 65 int flags; 66 67 flags = fcntl(sck, F_GETFL, 0); 68 flags |= O_NONBLOCK; 69 70 if (fcntl(sck, F_SETFL, flags)) 71 return -1; 72 73 return 0; 74 } 75 76 static char largeblock[1048576]; /* should be more than AF_UNIX sockbuf size */ 77 static int fd[2]; 78 static struct pollfd pfd0; 79 static struct pollfd pfd1; 80 81 void 82 setup(void) 83 { 84 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0) 85 err(1, "socketpair"); 86 if (set_nonblocking(fd[0]) == -1) 87 err(1, "fcntl"); 88 if (set_nonblocking(fd[1]) == -1) 89 err(1, "fcntl"); 90 pfd0.fd = fd[0]; 91 pfd0.events = POLLIN | POLLOUT; 92 pfd1.fd = fd[1]; 93 pfd1.events = POLLIN | POLLOUT; 94 } 95 96 int 97 main(void) 98 { 99 int num; 100 101 num = 1; 102 printf("1..18\n"); 103 fflush(stdout); 104 105 /* Large write with close */ 106 setup(); 107 if (poll(&pfd0, 1, 0) == -1) 108 err(1, "poll"); 109 report(num++, "initial 0", POLLOUT, pfd0.revents); 110 if (poll(&pfd1, 1, 0) == -1) 111 err(1, "poll"); 112 report(num++, "initial 1", POLLOUT, pfd1.revents); 113 if (write(fd[0], largeblock, sizeof(largeblock)) == -1) 114 err(1, "write"); 115 if (poll(&pfd0, 1, 0) == -1) 116 err(1, "poll"); 117 report(num++, "after large write", 0, pfd0.revents); 118 if (poll(&pfd1, 1, 0) == -1) 119 err(1, "poll"); 120 report(num++, "other side after large write", POLLIN | POLLOUT, pfd1.revents); 121 close(fd[0]); 122 if (poll(&pfd1, 1, 0) == -1) 123 err(1, "poll"); 124 report(num++, "other side after close", POLLIN | POLLHUP, pfd1.revents); 125 if (read(fd[1], largeblock, sizeof(largeblock)) == -1) 126 err(1, "read"); 127 if (poll(&pfd1, 1, 0) == -1) 128 err(1, "poll"); 129 report(num++, "other side after reading input", POLLHUP, pfd1.revents); 130 close(fd[1]); 131 132 /* With shutdown(SHUT_WR) */ 133 setup(); 134 if (shutdown(fd[0], SHUT_WR) == -1) 135 err(1, "shutdown"); 136 if (poll(&pfd0, 1, 0) == -1) 137 err(1, "poll"); 138 report(num++, "after shutdown(SHUT_WR)", POLLOUT, pfd0.revents); 139 if (poll(&pfd1, 1, 0) == -1) 140 err(1, "poll"); 141 report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents); 142 switch (read(fd[1], largeblock, sizeof(largeblock))) { 143 case 0: 144 break; 145 case -1: 146 err(1, "read after other side shutdown"); 147 break; 148 default: 149 errx(1, "kernel made up data that was never written"); 150 } 151 if (poll(&pfd1, 1, 0) == -1) 152 err(1, "poll"); 153 report(num++, "other side after reading EOF", POLLIN | POLLOUT, pfd1.revents); 154 if (write(fd[1], largeblock, sizeof(largeblock)) == -1) 155 err(1, "write"); 156 if (poll(&pfd0, 1, 0) == -1) 157 err(1, "poll"); 158 report(num++, "after data from other side", POLLIN | POLLOUT, pfd0.revents); 159 if (poll(&pfd1, 1, 0) == -1) 160 err(1, "poll"); 161 report(num++, "after writing", POLLIN, pfd1.revents); 162 if (shutdown(fd[1], SHUT_WR) == -1) 163 err(1, "shutdown second"); 164 if (poll(&pfd0, 1, 0) == -1) 165 err(1, "poll"); 166 report(num++, "after second shutdown", POLLIN | POLLHUP, pfd0.revents); 167 if (poll(&pfd1, 1, 0) == -1) 168 err(1, "poll"); 169 report(num++, "after second shutdown", POLLHUP, pfd1.revents); 170 close(fd[0]); 171 if (poll(&pfd1, 1, 0) == -1) 172 err(1, "poll"); 173 report(num++, "after close", POLLHUP, pfd1.revents); 174 close(fd[1]); 175 176 /* 177 * With shutdown(SHUT_RD) 178 * Note that shutdown(SHUT_WR) is passed to the peer, but 179 * shutdown(SHUT_RD) is not. 180 */ 181 setup(); 182 if (shutdown(fd[0], SHUT_RD) == -1) 183 err(1, "shutdown"); 184 if (poll(&pfd0, 1, 0) == -1) 185 err(1, "poll"); 186 report(num++, "after shutdown(SHUT_RD)", POLLIN | POLLOUT, pfd0.revents); 187 if (poll(&pfd1, 1, 0) == -1) 188 err(1, "poll"); 189 report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, pfd1.revents); 190 if (shutdown(fd[0], SHUT_WR) == -1) 191 err(1, "shutdown"); 192 if (poll(&pfd0, 1, 0) == -1) 193 err(1, "poll"); 194 report(num++, "after shutdown(SHUT_WR)", POLLHUP, pfd0.revents); 195 if (poll(&pfd1, 1, 0) == -1) 196 err(1, "poll"); 197 report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents); 198 close(fd[0]); 199 close(fd[1]); 200 201 return (0); 202 } 203