kqueue.c revision 134236
1/*- 2 * Copyright (c) 2004 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/tools/regression/sockets/kqueue/kqueue.c 134236 2004-08-24 04:02:41Z rwatson $ 27 */ 28 29#include <sys/types.h> 30#include <sys/event.h> 31#include <sys/socket.h> 32#include <sys/time.h> 33 34#include <errno.h> 35#include <fcntl.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <unistd.h> 40 41/*- 42 * This test uses UNIX domain socket pairs to perform some basic exercising 43 * of kqueue functionality on sockets. In particular, testing that for read 44 * and write filters, we see the correct detection of whether reads and 45 * writes should actually be able to occur. 46 * 47 * TODO: 48 * - Test read/write filters for listen/accept sockets. 49 * - Handle the XXXRW below regarding datagram sockets. 50 * - Test that watermark/buffer size "data" fields returned by kqueue are 51 * correct. 52 * - Check that kqueue does something sensible when the remote endpoing is 53 * closed. 54 */ 55 56static void 57fail(int error, const char *func, const char *socktype, const char *rest) 58{ 59 60 fprintf(stderr, "FAIL\n"); 61 62 if (socktype == NULL) 63 fprintf(stderr, "%s(): %s\n", func, strerror(error)); 64 else if (rest == NULL) 65 fprintf(stderr, "%s(%s): %s\n", func, socktype, 66 strerror(error)); 67 else 68 fprintf(stderr, "%s(%s, %s): %s\n", func, socktype, rest, 69 strerror(error)); 70 exit(-1); 71} 72 73static void 74fail_assertion(const char *func, const char *socktype, const char *rest, 75 const char *assertion) 76{ 77 78 fprintf(stderr, "FAIL\n"); 79 80 if (socktype == NULL) 81 fprintf(stderr, "%s(): assertion %s failed\n", func, 82 assertion); 83 else if (rest == NULL) 84 fprintf(stderr, "%s(%s): assertion %s failed\n", func, 85 socktype, assertion); 86 else 87 fprintf(stderr, "%s(%s, %s): assertion %s failed\n", func, 88 socktype, rest, assertion); 89 exit(-1); 90} 91 92/* 93 * Test read kevent on a socket pair: check to make sure endpoint 0 isn't 94 * readable when we start, then write to endpoint 1 and confirm that endpoint 95 * 0 is now readable. Drain the write, then check that it's not readable 96 * again. Use non-blocking kqueue operations and socket operations. 97 */ 98static void 99test_evfilt_read(int kq, int fd[2], const char *socktype) 100{ 101 struct timespec ts; 102 struct kevent ke; 103 ssize_t len; 104 char ch; 105 int i; 106 107 EV_SET(&ke, fd[0], EVFILT_READ, EV_ADD, 0, 0, NULL); 108 if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) 109 fail(errno, "kevent", socktype, "EVFILT_READ, EV_ADD"); 110 111 /* 112 * Confirm not readable to begin with, no I/O yet. 113 */ 114 ts.tv_sec = 0; 115 ts.tv_nsec = 0; 116 i = kevent(kq, NULL, 0, &ke, 1, &ts); 117 if (i == -1) 118 fail(errno, "kevent", socktype, "EVFILT_READ"); 119 if (i != 0) 120 fail_assertion("kevent", socktype, "EVFILT_READ", 121 "empty socket unreadable"); 122 123 /* 124 * Write a byte to one end. 125 */ 126 ch = 'a'; 127 len = write(fd[1], &ch, sizeof(ch)); 128 if (len == -1) 129 fail(errno, "write", socktype, NULL); 130 if (len != sizeof(ch)) 131 fail_assertion("write", socktype, NULL, "write length"); 132 133 /* 134 * Other end should now be readable. 135 */ 136 ts.tv_sec = 0; 137 ts.tv_nsec = 0; 138 i = kevent(kq, NULL, 0, &ke, 1, &ts); 139 if (i == -1) 140 fail(errno, "kevent", socktype, "EVFILT_READ"); 141 if (i != 1) 142 fail_assertion("kevent", socktype, "EVFILT_READ", 143 "non-empty socket unreadable"); 144 145 /* 146 * Read a byte to clear the readable state. 147 */ 148 len = read(fd[0], &ch, sizeof(ch)); 149 if (len == -1) 150 fail(errno, "read", socktype, NULL); 151 if (len != sizeof(ch)) 152 fail_assertion("read", socktype, NULL, "read length"); 153 154 /* 155 * Now re-check for readability. 156 */ 157 ts.tv_sec = 0; 158 ts.tv_nsec = 0; 159 i = kevent(kq, NULL, 0, &ke, 1, &ts); 160 if (i == -1) 161 fail(errno, "kevent", socktype, "EVFILT_READ"); 162 if (i != 0) 163 fail_assertion("kevent", socktype, "EVFILT_READ", 164 "empty socket unreadable"); 165 166 EV_SET(&ke, fd[0], EVFILT_READ, EV_DELETE, 0, 0, NULL); 167 if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) 168 fail(errno, "kevent", socktype, "EVFILT_READ, EV_DELETE"); 169} 170 171static void 172test_evfilt_write(int kq, int fd[2], const char *socktype) 173{ 174 struct timespec ts; 175 struct kevent ke; 176 ssize_t len; 177 char ch; 178 int i; 179 180 EV_SET(&ke, fd[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL); 181 if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) 182 fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_ADD"); 183 184 /* 185 * Confirm writable to begin with, no I/O yet. 186 */ 187 ts.tv_sec = 0; 188 ts.tv_nsec = 0; 189 i = kevent(kq, NULL, 0, &ke, 1, &ts); 190 if (i == -1) 191 fail(errno, "kevent", socktype, "EVFILT_WRITE"); 192 if (i != 1) 193 fail_assertion("kevent", socktype, "EVFILT_WRITE", 194 "empty socket unwritable"); 195 196 /* 197 * Write bytes into the socket until we can't write anymore. 198 */ 199 ch = 'a'; 200 while ((len = write(fd[0], &ch, sizeof(ch))) == sizeof(ch)) {}; 201 if (len == -1 && errno != EAGAIN && errno != ENOBUFS) 202 fail(errno, "write", socktype, NULL); 203 if (len != -1 && len != sizeof(ch)) 204 fail_assertion("write", socktype, NULL, "write length"); 205 206 /* 207 * Check to make sure the socket is no longer writable. 208 */ 209 ts.tv_sec = 0; 210 ts.tv_nsec = 0; 211 i = kevent(kq, NULL, 0, &ke, 1, &ts); 212 if (i == -1) 213 fail(errno, "kevent", socktype, "EVFILT_WRITE"); 214 if (i != 0) 215 fail_assertion("kevent", socktype, "EVFILT_WRITE", 216 "full socket writable"); 217 218 EV_SET(&ke, fd[0], EVFILT_WRITE, EV_DELETE, 0, 0, NULL); 219 if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) 220 fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_DELETE"); 221} 222 223/* 224 * Basic registration exercise for kqueue(2). Create several types/brands of 225 * sockets, and confirm that we can register for various events on them. 226 */ 227int 228main(int argc, char *argv[]) 229{ 230 int i, kq, sv[2]; 231 232 kq = kqueue(); 233 if (kq == -1) 234 fail(errno, "kqueue", NULL, NULL); 235 236 /* 237 * Create a UNIX domain datagram socket, and attach/test/detach a 238 * read filter on it. 239 */ 240 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1) 241 fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL); 242 243 i = O_NONBLOCK; 244 if (fcntl(sv[0], F_SETFL, &i) != 0) 245 fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); 246 if (fcntl(sv[1], F_SETFL, &i) != 0) 247 fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); 248 249 test_evfilt_read(kq, sv, "PF_UNIX, SOCK_DGRAM"); 250 251 if (close(sv[0]) == -1) 252 fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]"); 253 if (close(sv[1]) == -1) 254 fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]"); 255 256#if 0 257 /* 258 * XXXRW: We disable the write test in the case of datagram sockets, 259 * as kqueue can't tell when the remote socket receive buffer is 260 * full, whereas the UNIX domain socket implementation can tell and 261 * returns ENOBUFS. 262 */ 263 /* 264 * Create a UNIX domain datagram socket, and attach/test/detach a 265 * write filter on it. 266 */ 267 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1) 268 fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL); 269 270 i = O_NONBLOCK; 271 if (fcntl(sv[0], F_SETFL, &i) != 0) 272 fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); 273 if (fcntl(sv[1], F_SETFL, &i) != 0) 274 fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); 275 276 test_evfilt_write(kq, sv, "PF_UNIX, SOCK_DGRAM"); 277 278 if (close(sv[0]) == -1) 279 fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]"); 280 if (close(sv[1]) == -1) 281 fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]"); 282#endif 283 284 /* 285 * Create a UNIX domain stream socket, and attach/test/detach a 286 * read filter on it. 287 */ 288 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) 289 fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL); 290 291 i = O_NONBLOCK; 292 if (fcntl(sv[0], F_SETFL, &i) != 0) 293 fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); 294 if (fcntl(sv[1], F_SETFL, &i) != 0) 295 fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); 296 297 test_evfilt_read(kq, sv, "PF_UNIX, SOCK_STREAM"); 298 299 if (close(sv[0]) == -1) 300 fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]"); 301 if (close(sv[1]) == -1) 302 fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]"); 303 304 /* 305 * Create a UNIX domain stream socket, and attach/test/detach a 306 * write filter on it. 307 */ 308 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) 309 fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL); 310 311 i = O_NONBLOCK; 312 if (fcntl(sv[0], F_SETFL, &i) != 0) 313 fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); 314 if (fcntl(sv[1], F_SETFL, &i) != 0) 315 fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); 316 317 test_evfilt_write(kq, sv, "PF_UNIX, SOCK_STREAM"); 318 319 if (close(sv[0]) == -1) 320 fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]"); 321 if (close(sv[1]) == -1) 322 fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]"); 323 324 if (close(kq) == -1) 325 fail(errno, "close", "kq", NULL); 326 327 printf("PASS\n"); 328 return (0); 329} 330