summaryrefslogtreecommitdiff
path: root/tests/kernel/kqueue
diff options
context:
space:
mode:
authorthorpej <thorpej@NetBSD.org>2021-10-02 18:39:15 +0000
committerthorpej <thorpej@NetBSD.org>2021-10-02 18:39:15 +0000
commit763357c3ee2624d0c4454297972dcb05d840ce05 (patch)
tree3a6f3fbb233b658182a5fe99f5a2b2531f8ec15b /tests/kernel/kqueue
parentadb6b0ec95cbbbf720ddb9034d64b9bf20c0c5c5 (diff)
- Add a new EVFILT_WRITE test case for FIFOs that correctly validates
the writability thresholds. - Fix a bug in fifo_kqfilter() exposed by the new test case; in the EVFILT_WRITE case, we were attaching the wrong end of the socket pair to the knote! - In filt_fiforead(), use ">= so->so_rcv.sb_lowat" rather than "> 0" for consistency with fifo_poll(). NFC.
Diffstat (limited to 'tests/kernel/kqueue')
-rw-r--r--tests/kernel/kqueue/write/t_fifo.c132
1 files changed, 90 insertions, 42 deletions
diff --git a/tests/kernel/kqueue/write/t_fifo.c b/tests/kernel/kqueue/write/t_fifo.c
index fe375b8fa94..de1550466bb 100644
--- a/tests/kernel/kqueue/write/t_fifo.c
+++ b/tests/kernel/kqueue/write/t_fifo.c
@@ -1,11 +1,11 @@
-/* $NetBSD: t_fifo.c,v 1.4 2017/01/13 21:30:41 christos Exp $ */
+/* $NetBSD: t_fifo.c,v 1.5 2021/10/02 18:39:15 thorpej Exp $ */
/*-
- * Copyright (c) 2002, 2008 The NetBSD Foundation, Inc.
+ * Copyright (c) 2021 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
- * by Luke Mewburn and Jaromir Dolecek.
+ * by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,68 +30,116 @@
*/
#include <sys/cdefs.h>
-__COPYRIGHT("@(#) Copyright (c) 2008\
+__COPYRIGHT("@(#) Copyright (c) 2021\
The NetBSD Foundation, inc. All rights reserved.");
-__RCSID("$NetBSD: t_fifo.c,v 1.4 2017/01/13 21:30:41 christos Exp $");
+__RCSID("$NetBSD: t_fifo.c,v 1.5 2021/10/02 18:39:15 thorpej Exp $");
#include <sys/event.h>
#include <sys/stat.h>
-#include <sys/wait.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <inttypes.h>
#include <atf-c.h>
-#include "h_macros.h"
+static const char fifo_path[] = "fifo";
-#define FIFONAME "fifo"
+static void
+fifo_support(void)
+{
+ errno = 0;
+ if (mkfifo(fifo_path, 0600) == 0) {
+ ATF_REQUIRE(unlink(fifo_path) == 0);
+ return;
+ }
+
+ if (errno == EOPNOTSUPP) {
+ atf_tc_skip("the kernel does not support FIFOs");
+ } else {
+ atf_tc_fail("mkfifo(2) failed");
+ }
+}
-ATF_TC(fifo);
+ATF_TC_WITH_CLEANUP(fifo);
ATF_TC_HEAD(fifo, tc)
{
- atf_tc_set_md_var(tc, "descr", "Checks EVFILT_WRITE for fifo");
+ atf_tc_set_md_var(tc, "descr", "Checks EVFILT_WRITE on fifo");
}
ATF_TC_BODY(fifo, tc)
{
- char buffer[128];
+ const struct timespec to = { 0, 0 };
struct kevent event[1];
- pid_t child;
- int kq, n, fd, status;
-
- RL(mkfifo(FIFONAME, 0644));
- RL(fd = open(FIFONAME, O_RDWR, 0644));
- RL(kq = kqueue());
-
- /* spawn child reader */
- RL(child = fork());
- if (child == 0) {
- int sz = read(fd, buffer, 128);
- if (sz > 0)
- (void)printf("fifo: child read '%.*s'\n", sz, buffer);
- _exit(sz <= 0);
+ char *buf;
+ int rfd, wfd, kq;
+ long pipe_buf;
+
+ fifo_support();
+
+ ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0);
+ ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0);
+ ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY | O_NONBLOCK)) >= 0);
+ ATF_REQUIRE((kq = kqueue()) >= 0);
+
+ /* Get the maximum atomic pipe write size. */
+ pipe_buf = fpathconf(wfd, _PC_PIPE_BUF);
+ ATF_REQUIRE(pipe_buf > 1);
+
+ buf = malloc(pipe_buf);
+ ATF_REQUIRE(buf != NULL);
+
+ EV_SET(&event[0], wfd, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, 0);
+ ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0);
+
+ /* We expect the FIFO to be writable. */
+ ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &to) == 1);
+ ATF_REQUIRE(event[0].ident == (uintptr_t)wfd);
+ ATF_REQUIRE(event[0].filter == EVFILT_WRITE);
+
+ /*
+ * Write data into the FIFO until it is full, which is
+ * defined as insufficient buffer space to hold the
+ * maximum atomic pipe write size.
+ */
+ while (write(wfd, buf, pipe_buf) != -1) {
+ continue;
}
+ ATF_REQUIRE(errno == EAGAIN);
+
+ /* We expect the FIFO to no longer be writable. */
+ ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &to) == 0);
+
+ /* Read a single byte of data from the FIFO. */
+ ATF_REQUIRE(read(rfd, buf, 1) == 1);
+
+ /*
+ * Because we have read only a single byte out, there will
+ * be insufficient space for a pipe_buf-sized message, so
+ * the FIFO should still not be writable.
+ */
+ ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &to) == 0);
+
+ /*
+ * Now read enough so that exactly pipe_buf space should be
+ * available. The FIFO should be writable after that.
+ */
+ ATF_REQUIRE(read(rfd, buf, pipe_buf - 1) == pipe_buf - 1);
+ ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &to) == 1);
+ ATF_REQUIRE(event[0].ident == (uintptr_t)wfd);
+ ATF_REQUIRE(event[0].filter == EVFILT_WRITE);
+
+ (void)close(wfd);
+ (void)close(rfd);
+ (void)close(kq);
+}
- EV_SET(&event[0], fd, EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, 0, 0);
- RL(kevent(kq, event, 1, NULL, 0, NULL));
-
- (void)memset(event, 0, sizeof(event));
- RL(n = kevent(kq, NULL, 0, event, 1, NULL));
-
- (void)printf("kevent num %d filt %d flags: %#x, fflags: %#x, "
- "data: %" PRId64 "\n", n, event[0].filter, event[0].flags,
- event[0].fflags, event[0].data);
-
- ATF_REQUIRE_EQ(event[0].filter, EVFILT_WRITE);
-
- RL(write(fd, "foo", 3));
- (void)printf("fifo: wrote 'foo'\n");
- RL(close(fd));
-
- (void)waitpid(child, &status, 0);
+ATF_TC_CLEANUP(fifo, tc)
+{
+ (void)unlink(fifo_path);
}
ATF_TP_ADD_TCS(tp)