xref: /freebsd/tools/regression/sockets/kqueue/kqueue.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
162967fb0SRobert Watson /*-
262967fb0SRobert Watson  * Copyright (c) 2004 Robert N. M. Watson
362967fb0SRobert Watson  * All rights reserved.
462967fb0SRobert Watson  *
562967fb0SRobert Watson  * Redistribution and use in source and binary forms, with or without
662967fb0SRobert Watson  * modification, are permitted provided that the following conditions
762967fb0SRobert Watson  * are met:
862967fb0SRobert Watson  * 1. Redistributions of source code must retain the above copyright
962967fb0SRobert Watson  *    notice, this list of conditions and the following disclaimer.
1062967fb0SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
1162967fb0SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
1262967fb0SRobert Watson  *    documentation and/or other materials provided with the distribution.
1362967fb0SRobert Watson  *
1462967fb0SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1562967fb0SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1662967fb0SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1762967fb0SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1862967fb0SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1962967fb0SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2062967fb0SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2162967fb0SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2262967fb0SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2362967fb0SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2462967fb0SRobert Watson  * SUCH DAMAGE.
2562967fb0SRobert Watson  */
2662967fb0SRobert Watson 
2762967fb0SRobert Watson #include <sys/types.h>
2862967fb0SRobert Watson #include <sys/event.h>
2962967fb0SRobert Watson #include <sys/socket.h>
3062967fb0SRobert Watson #include <sys/time.h>
3162967fb0SRobert Watson 
3262967fb0SRobert Watson #include <errno.h>
3362967fb0SRobert Watson #include <fcntl.h>
3462967fb0SRobert Watson #include <stdio.h>
3562967fb0SRobert Watson #include <stdlib.h>
3662967fb0SRobert Watson #include <string.h>
3762967fb0SRobert Watson #include <unistd.h>
3862967fb0SRobert Watson 
3900e13b1dSNik Clayton static int	curtest = 1;
4000e13b1dSNik Clayton 
4162967fb0SRobert Watson /*-
4262967fb0SRobert Watson  * This test uses UNIX domain socket pairs to perform some basic exercising
4362967fb0SRobert Watson  * of kqueue functionality on sockets.  In particular, testing that for read
4462967fb0SRobert Watson  * and write filters, we see the correct detection of whether reads and
4562967fb0SRobert Watson  * writes should actually be able to occur.
4662967fb0SRobert Watson  *
4762967fb0SRobert Watson  * TODO:
4862967fb0SRobert Watson  * - Test read/write filters for listen/accept sockets.
4962967fb0SRobert Watson  * - Handle the XXXRW below regarding datagram sockets.
5062967fb0SRobert Watson  * - Test that watermark/buffer size "data" fields returned by kqueue are
5162967fb0SRobert Watson  *   correct.
5262967fb0SRobert Watson  * - Check that kqueue does something sensible when the remote endpoing is
5362967fb0SRobert Watson  *   closed.
5462967fb0SRobert Watson  */
5562967fb0SRobert Watson 
5600e13b1dSNik Clayton #define OK(testname)	printf("ok %d - %s\n", curtest, testname); \
5700e13b1dSNik Clayton 			curtest++;
5800e13b1dSNik Clayton 
5962967fb0SRobert Watson static void
fail(int error,const char * func,const char * socktype,const char * rest)6062967fb0SRobert Watson fail(int error, const char *func, const char *socktype, const char *rest)
6162967fb0SRobert Watson {
6262967fb0SRobert Watson 
6300e13b1dSNik Clayton 	printf("not ok %d\n", curtest);
6462967fb0SRobert Watson 
6562967fb0SRobert Watson 	if (socktype == NULL)
6600e13b1dSNik Clayton 		printf("# %s(): %s\n", func, strerror(error));
6762967fb0SRobert Watson 	else if (rest == NULL)
6800e13b1dSNik Clayton 		printf("# %s(%s): %s\n", func, socktype,
6962967fb0SRobert Watson 		    strerror(error));
7062967fb0SRobert Watson 	else
7100e13b1dSNik Clayton 		printf("# %s(%s, %s): %s\n", func, socktype, rest,
7262967fb0SRobert Watson 		    strerror(error));
7362967fb0SRobert Watson 	exit(-1);
7462967fb0SRobert Watson }
7562967fb0SRobert Watson 
7662967fb0SRobert Watson static void
fail_assertion(const char * func,const char * socktype,const char * rest,const char * assertion)7762967fb0SRobert Watson fail_assertion(const char *func, const char *socktype, const char *rest,
7862967fb0SRobert Watson     const char *assertion)
7962967fb0SRobert Watson {
8062967fb0SRobert Watson 
8100e13b1dSNik Clayton 	printf("not ok %d - %s\n", curtest, assertion);
8262967fb0SRobert Watson 
8362967fb0SRobert Watson 	if (socktype == NULL)
8400e13b1dSNik Clayton 		printf("# %s(): assertion %s failed\n", func,
8562967fb0SRobert Watson 		    assertion);
8662967fb0SRobert Watson 	else if (rest == NULL)
8700e13b1dSNik Clayton 		printf("# %s(%s): assertion %s failed\n", func,
8862967fb0SRobert Watson 		    socktype, assertion);
8962967fb0SRobert Watson 	else
9000e13b1dSNik Clayton 		printf("# %s(%s, %s): assertion %s failed\n", func,
9162967fb0SRobert Watson 		    socktype, rest, assertion);
9262967fb0SRobert Watson 	exit(-1);
9362967fb0SRobert Watson }
9462967fb0SRobert Watson 
9562967fb0SRobert Watson /*
9662967fb0SRobert Watson  * Test read kevent on a socket pair: check to make sure endpoint 0 isn't
9762967fb0SRobert Watson  * readable when we start, then write to endpoint 1 and confirm that endpoint
9862967fb0SRobert Watson  * 0 is now readable.  Drain the write, then check that it's not readable
9962967fb0SRobert Watson  * again.  Use non-blocking kqueue operations and socket operations.
10062967fb0SRobert Watson  */
10162967fb0SRobert Watson static void
test_evfilt_read(int kq,int fd[2],const char * socktype)10262967fb0SRobert Watson test_evfilt_read(int kq, int fd[2], const char *socktype)
10362967fb0SRobert Watson {
10462967fb0SRobert Watson 	struct timespec ts;
10562967fb0SRobert Watson 	struct kevent ke;
10662967fb0SRobert Watson 	ssize_t len;
10762967fb0SRobert Watson 	char ch;
10862967fb0SRobert Watson 	int i;
10962967fb0SRobert Watson 
11062967fb0SRobert Watson 	EV_SET(&ke, fd[0], EVFILT_READ, EV_ADD, 0, 0, NULL);
11162967fb0SRobert Watson 	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
11262967fb0SRobert Watson 		fail(errno, "kevent", socktype, "EVFILT_READ, EV_ADD");
11300e13b1dSNik Clayton 	OK("EVFILT_READ, EV_ADD");
11462967fb0SRobert Watson 
11562967fb0SRobert Watson 	/*
11662967fb0SRobert Watson 	 * Confirm not readable to begin with, no I/O yet.
11762967fb0SRobert Watson 	 */
11862967fb0SRobert Watson 	ts.tv_sec = 0;
11962967fb0SRobert Watson 	ts.tv_nsec = 0;
12062967fb0SRobert Watson 	i = kevent(kq, NULL, 0, &ke, 1, &ts);
12162967fb0SRobert Watson 	if (i == -1)
12262967fb0SRobert Watson 		fail(errno, "kevent", socktype, "EVFILT_READ");
12300e13b1dSNik Clayton 	OK("EVFILT_READ");
12462967fb0SRobert Watson 	if (i != 0)
12562967fb0SRobert Watson 		fail_assertion("kevent", socktype, "EVFILT_READ",
12662967fb0SRobert Watson 		    "empty socket unreadable");
12700e13b1dSNik Clayton 	OK("empty socket unreadable");
12862967fb0SRobert Watson 
12962967fb0SRobert Watson 	/*
13062967fb0SRobert Watson 	 * Write a byte to one end.
13162967fb0SRobert Watson 	 */
13262967fb0SRobert Watson 	ch = 'a';
13362967fb0SRobert Watson 	len = write(fd[1], &ch, sizeof(ch));
13462967fb0SRobert Watson 	if (len == -1)
13562967fb0SRobert Watson 		fail(errno, "write", socktype, NULL);
13600e13b1dSNik Clayton 	OK("write one byte");
13762967fb0SRobert Watson 	if (len != sizeof(ch))
13862967fb0SRobert Watson 		fail_assertion("write", socktype, NULL, "write length");
13900e13b1dSNik Clayton 	OK("write one byte length");
14062967fb0SRobert Watson 
14162967fb0SRobert Watson 	/*
14262967fb0SRobert Watson 	 * Other end should now be readable.
14362967fb0SRobert Watson 	 */
14462967fb0SRobert Watson 	ts.tv_sec = 0;
14562967fb0SRobert Watson 	ts.tv_nsec = 0;
14662967fb0SRobert Watson 	i = kevent(kq, NULL, 0, &ke, 1, &ts);
14762967fb0SRobert Watson 	if (i == -1)
14862967fb0SRobert Watson 		fail(errno, "kevent", socktype, "EVFILT_READ");
14900e13b1dSNik Clayton 	OK("EVFILT_READ");
15062967fb0SRobert Watson 	if (i != 1)
15162967fb0SRobert Watson 		fail_assertion("kevent", socktype, "EVFILT_READ",
15262967fb0SRobert Watson 		    "non-empty socket unreadable");
15300e13b1dSNik Clayton 	OK("non-empty socket unreadable");
15462967fb0SRobert Watson 
15562967fb0SRobert Watson 	/*
15662967fb0SRobert Watson 	 * Read a byte to clear the readable state.
15762967fb0SRobert Watson 	 */
15862967fb0SRobert Watson 	len = read(fd[0], &ch, sizeof(ch));
15962967fb0SRobert Watson 	if (len == -1)
16062967fb0SRobert Watson 		fail(errno, "read", socktype, NULL);
16100e13b1dSNik Clayton 	OK("read one byte");
16262967fb0SRobert Watson 	if (len != sizeof(ch))
16362967fb0SRobert Watson 		fail_assertion("read", socktype, NULL, "read length");
16400e13b1dSNik Clayton 	OK("read one byte length");
16562967fb0SRobert Watson 
16662967fb0SRobert Watson 	/*
16762967fb0SRobert Watson 	 * Now re-check for readability.
16862967fb0SRobert Watson 	 */
16962967fb0SRobert Watson 	ts.tv_sec = 0;
17062967fb0SRobert Watson 	ts.tv_nsec = 0;
17162967fb0SRobert Watson 	i = kevent(kq, NULL, 0, &ke, 1, &ts);
17262967fb0SRobert Watson 	if (i == -1)
17362967fb0SRobert Watson 		fail(errno, "kevent", socktype, "EVFILT_READ");
17400e13b1dSNik Clayton 	OK("EVFILT_READ");
17562967fb0SRobert Watson 	if (i != 0)
17662967fb0SRobert Watson 		fail_assertion("kevent", socktype, "EVFILT_READ",
17762967fb0SRobert Watson 		    "empty socket unreadable");
17800e13b1dSNik Clayton 	OK("empty socket unreadable");
17962967fb0SRobert Watson 
18062967fb0SRobert Watson 	EV_SET(&ke, fd[0], EVFILT_READ, EV_DELETE, 0, 0, NULL);
18162967fb0SRobert Watson 	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
18262967fb0SRobert Watson 		fail(errno, "kevent", socktype, "EVFILT_READ, EV_DELETE");
18300e13b1dSNik Clayton 	OK("EVFILT_READ, EV_DELETE");
18462967fb0SRobert Watson }
18562967fb0SRobert Watson 
18662967fb0SRobert Watson static void
test_evfilt_write(int kq,int fd[2],const char * socktype)18762967fb0SRobert Watson test_evfilt_write(int kq, int fd[2], const char *socktype)
18862967fb0SRobert Watson {
18962967fb0SRobert Watson 	struct timespec ts;
19062967fb0SRobert Watson 	struct kevent ke;
19162967fb0SRobert Watson 	ssize_t len;
19262967fb0SRobert Watson 	char ch;
19362967fb0SRobert Watson 	int i;
19462967fb0SRobert Watson 
19562967fb0SRobert Watson 	EV_SET(&ke, fd[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL);
19662967fb0SRobert Watson 	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
19762967fb0SRobert Watson 		fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_ADD");
19800e13b1dSNik Clayton 	OK("EVFILE_WRITE, EV_ADD");
19962967fb0SRobert Watson 
20062967fb0SRobert Watson 	/*
20162967fb0SRobert Watson 	 * Confirm writable to begin with, no I/O yet.
20262967fb0SRobert Watson 	 */
20362967fb0SRobert Watson 	ts.tv_sec = 0;
20462967fb0SRobert Watson 	ts.tv_nsec = 0;
20562967fb0SRobert Watson 	i = kevent(kq, NULL, 0, &ke, 1, &ts);
20662967fb0SRobert Watson 	if (i == -1)
20762967fb0SRobert Watson 		fail(errno, "kevent", socktype, "EVFILT_WRITE");
20800e13b1dSNik Clayton 	OK("EVFILE_WRITE");
20962967fb0SRobert Watson 	if (i != 1)
21062967fb0SRobert Watson 		fail_assertion("kevent", socktype, "EVFILT_WRITE",
21162967fb0SRobert Watson 		    "empty socket unwritable");
21200e13b1dSNik Clayton 	OK("empty socket unwritable");
21362967fb0SRobert Watson 
21462967fb0SRobert Watson 	/*
21562967fb0SRobert Watson 	 * Write bytes into the socket until we can't write anymore.
21662967fb0SRobert Watson 	 */
21762967fb0SRobert Watson 	ch = 'a';
21862967fb0SRobert Watson 	while ((len = write(fd[0], &ch, sizeof(ch))) == sizeof(ch)) {};
21962967fb0SRobert Watson 	if (len == -1 && errno != EAGAIN && errno != ENOBUFS)
22062967fb0SRobert Watson 		fail(errno, "write", socktype, NULL);
22100e13b1dSNik Clayton 	OK("write");
22262967fb0SRobert Watson 	if (len != -1 && len != sizeof(ch))
22362967fb0SRobert Watson 		fail_assertion("write", socktype, NULL, "write length");
22400e13b1dSNik Clayton 	OK("write length");
22562967fb0SRobert Watson 
22662967fb0SRobert Watson 	/*
22762967fb0SRobert Watson 	 * Check to make sure the socket is no longer writable.
22862967fb0SRobert Watson 	 */
22962967fb0SRobert Watson 	ts.tv_sec = 0;
23062967fb0SRobert Watson 	ts.tv_nsec = 0;
23162967fb0SRobert Watson 	i = kevent(kq, NULL, 0, &ke, 1, &ts);
23262967fb0SRobert Watson 	if (i == -1)
23362967fb0SRobert Watson 		fail(errno, "kevent", socktype, "EVFILT_WRITE");
23400e13b1dSNik Clayton 	OK("EVFILT_WRITE");
23562967fb0SRobert Watson 	if (i != 0)
23662967fb0SRobert Watson 		fail_assertion("kevent", socktype, "EVFILT_WRITE",
23762967fb0SRobert Watson 		    "full socket writable");
23800e13b1dSNik Clayton 	OK("full socket writable");
23962967fb0SRobert Watson 
24062967fb0SRobert Watson 	EV_SET(&ke, fd[0], EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
24162967fb0SRobert Watson 	if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1)
24262967fb0SRobert Watson 		fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_DELETE");
24300e13b1dSNik Clayton 	OK("EVFILT_WRITE, EV_DELETE");
24462967fb0SRobert Watson }
24562967fb0SRobert Watson 
24662967fb0SRobert Watson /*
24762967fb0SRobert Watson  * Basic registration exercise for kqueue(2).  Create several types/brands of
24862967fb0SRobert Watson  * sockets, and confirm that we can register for various events on them.
24962967fb0SRobert Watson  */
25062967fb0SRobert Watson int
main(void)251*957885bfSEnji Cooper main(void)
25262967fb0SRobert Watson {
253*957885bfSEnji Cooper 	int kq, sv[2];
25462967fb0SRobert Watson 
25500e13b1dSNik Clayton 	printf("1..49\n");
25600e13b1dSNik Clayton 
25762967fb0SRobert Watson 	kq = kqueue();
25862967fb0SRobert Watson 	if (kq == -1)
25962967fb0SRobert Watson 		fail(errno, "kqueue", NULL, NULL);
26000e13b1dSNik Clayton 	OK("kqueue()");
26162967fb0SRobert Watson 
26262967fb0SRobert Watson 	/*
26362967fb0SRobert Watson 	 * Create a UNIX domain datagram socket, and attach/test/detach a
26462967fb0SRobert Watson 	 * read filter on it.
26562967fb0SRobert Watson 	 */
26662967fb0SRobert Watson 	if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
26762967fb0SRobert Watson 		fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL);
26800e13b1dSNik Clayton 	OK("socketpair() 1");
26962967fb0SRobert Watson 
270accbe494SRobert Watson 	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
27162967fb0SRobert Watson 		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
27200e13b1dSNik Clayton 	OK("fcntl() 1");
273accbe494SRobert Watson 	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
27462967fb0SRobert Watson 		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
27500e13b1dSNik Clayton 	OK("fnctl() 2");
27662967fb0SRobert Watson 
27762967fb0SRobert Watson 	test_evfilt_read(kq, sv, "PF_UNIX, SOCK_DGRAM");
27862967fb0SRobert Watson 
27962967fb0SRobert Watson 	if (close(sv[0]) == -1)
28062967fb0SRobert Watson 		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]");
28100e13b1dSNik Clayton 	OK("close() 1");
28262967fb0SRobert Watson 	if (close(sv[1]) == -1)
28362967fb0SRobert Watson 		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]");
28400e13b1dSNik Clayton 	OK("close() 2");
28562967fb0SRobert Watson 
28662967fb0SRobert Watson #if 0
28762967fb0SRobert Watson 	/*
28862967fb0SRobert Watson 	 * XXXRW: We disable the write test in the case of datagram sockets,
28962967fb0SRobert Watson 	 * as kqueue can't tell when the remote socket receive buffer is
29062967fb0SRobert Watson 	 * full, whereas the UNIX domain socket implementation can tell and
29162967fb0SRobert Watson 	 * returns ENOBUFS.
29262967fb0SRobert Watson 	 */
29362967fb0SRobert Watson 	/*
29462967fb0SRobert Watson 	 * Create a UNIX domain datagram socket, and attach/test/detach a
29562967fb0SRobert Watson 	 * write filter on it.
29662967fb0SRobert Watson 	 */
29762967fb0SRobert Watson 	if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
29862967fb0SRobert Watson 		fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL);
29962967fb0SRobert Watson 
300accbe494SRobert Watson 	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
30162967fb0SRobert Watson 		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
302accbe494SRobert Watson 	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
30362967fb0SRobert Watson 		fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK");
30462967fb0SRobert Watson 
30562967fb0SRobert Watson 	test_evfilt_write(kq, sv, "PF_UNIX, SOCK_DGRAM");
30662967fb0SRobert Watson 
30762967fb0SRobert Watson 	if (close(sv[0]) == -1)
30862967fb0SRobert Watson 		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]");
30962967fb0SRobert Watson 	if (close(sv[1]) == -1)
31062967fb0SRobert Watson 		fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]");
31162967fb0SRobert Watson #endif
31262967fb0SRobert Watson 
31362967fb0SRobert Watson 	/*
31462967fb0SRobert Watson 	 * Create a UNIX domain stream socket, and attach/test/detach a
31562967fb0SRobert Watson 	 * read filter on it.
31662967fb0SRobert Watson 	 */
31762967fb0SRobert Watson 	if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
31862967fb0SRobert Watson 		fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL);
31900e13b1dSNik Clayton 	OK("socketpair() 2");
32062967fb0SRobert Watson 
321accbe494SRobert Watson 	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
32262967fb0SRobert Watson 		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
32300e13b1dSNik Clayton 	OK("fcntl() 3");
324accbe494SRobert Watson 	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
32562967fb0SRobert Watson 		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
32600e13b1dSNik Clayton 	OK("fcntl() 4");
32762967fb0SRobert Watson 
32862967fb0SRobert Watson 	test_evfilt_read(kq, sv, "PF_UNIX, SOCK_STREAM");
32962967fb0SRobert Watson 
33062967fb0SRobert Watson 	if (close(sv[0]) == -1)
33162967fb0SRobert Watson 		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]");
33200e13b1dSNik Clayton 	OK("close() 3");
33362967fb0SRobert Watson 	if (close(sv[1]) == -1)
33462967fb0SRobert Watson 		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]");
33500e13b1dSNik Clayton 	OK("close() 4");
33662967fb0SRobert Watson 
33762967fb0SRobert Watson 	/*
33862967fb0SRobert Watson 	 * Create a UNIX domain stream socket, and attach/test/detach a
33962967fb0SRobert Watson 	 * write filter on it.
34062967fb0SRobert Watson 	 */
34162967fb0SRobert Watson 	if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
34262967fb0SRobert Watson 		fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL);
34300e13b1dSNik Clayton 	OK("socketpair() 3");
34462967fb0SRobert Watson 
345accbe494SRobert Watson 	if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0)
34662967fb0SRobert Watson 		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
34700e13b1dSNik Clayton 	OK("fcntl() 5");
348accbe494SRobert Watson 	if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0)
34962967fb0SRobert Watson 		fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK");
35000e13b1dSNik Clayton 	OK("fcntl() 6");
35162967fb0SRobert Watson 
35262967fb0SRobert Watson 	test_evfilt_write(kq, sv, "PF_UNIX, SOCK_STREAM");
35362967fb0SRobert Watson 
35462967fb0SRobert Watson 	if (close(sv[0]) == -1)
35562967fb0SRobert Watson 		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]");
35600e13b1dSNik Clayton 	OK("close() 5");
35762967fb0SRobert Watson 	if (close(sv[1]) == -1)
35862967fb0SRobert Watson 		fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]");
35900e13b1dSNik Clayton 	OK("close() 6");
36062967fb0SRobert Watson 
36162967fb0SRobert Watson 	if (close(kq) == -1)
36262967fb0SRobert Watson 		fail(errno, "close", "kq", NULL);
36300e13b1dSNik Clayton 	OK("close() 7");
36462967fb0SRobert Watson 
36562967fb0SRobert Watson 	return (0);
36662967fb0SRobert Watson }
367