Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 Feb 2025 22:08:37 GMT
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: bc7ee0b52a8d - main - tests/unix_stream: add test that checks a full socket isn't writable
Message-ID:  <202502102208.51AM8b5h039634@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=bc7ee0b52a8dd613711c7225244aac954b41e534

commit bc7ee0b52a8dd613711c7225244aac954b41e534
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-02-10 21:53:41 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-02-10 22:01:16 +0000

    tests/unix_stream: add test that checks a full socket isn't writable
---
 tests/sys/kern/unix_stream.c | 86 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 81 insertions(+), 5 deletions(-)

diff --git a/tests/sys/kern/unix_stream.c b/tests/sys/kern/unix_stream.c
index d57cfad020fa..49aabdaa0943 100644
--- a/tests/sys/kern/unix_stream.c
+++ b/tests/sys/kern/unix_stream.c
@@ -26,14 +26,15 @@
  */
 
 #include <sys/cdefs.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <signal.h>
 #include <sys/socket.h>
+#include <sys/event.h>
+#include <sys/sysctl.h>
 #include <sys/un.h>
-
+#include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <poll.h>
 
 #include <atf-c.h>
 
@@ -49,6 +50,18 @@ do_socketpair(int *sv)
 	ATF_REQUIRE(sv[0] != sv[1]);
 }
 
+static u_long
+getsendspace(void)
+{
+	u_long sendspace;
+
+	ATF_REQUIRE_MSG(sysctlbyname("net.local.stream.sendspace", &sendspace,
+	    &(size_t){sizeof(u_long)}, NULL, 0) != -1,
+	    "sysctl net.local.stream.sendspace failed: %s", strerror(errno));
+
+	return (sendspace);
+}
+
 /* getpeereid(3) should work with stream sockets created via socketpair(2) */
 ATF_TC_WITHOUT_HEAD(getpeereid);
 ATF_TC_BODY(getpeereid, tc)
@@ -86,11 +99,74 @@ ATF_TC_BODY(send_0, tc)
 	close(sv[1]);
 }
 
+static void
+check_writable(int fd, int expect)
+{
+	fd_set wrfds;
+	struct pollfd pfd[1];
+	struct kevent kev;
+	int nfds, kq;
+
+	FD_ZERO(&wrfds);
+	FD_SET(fd, &wrfds);
+	nfds = select(fd + 1, NULL, &wrfds, NULL,
+	    &(struct timeval){.tv_usec = 1000});
+	ATF_REQUIRE_MSG(nfds == expect,
+	    "select() returns %d errno %d", nfds, errno);
+
+	pfd[0] = (struct pollfd){
+		.fd = fd,
+		.events = POLLOUT | POLLWRNORM,
+	};
+	nfds = poll(pfd, 1, 1);
+	ATF_REQUIRE_MSG(nfds == expect,
+	    "poll() returns %d errno %d", nfds, errno);
+
+	ATF_REQUIRE(kq = kqueue());
+	EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
+	ATF_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0);
+	nfds = kevent(kq, NULL, 0, &kev, 1,
+	    &(struct timespec){.tv_nsec = 1000000});
+	ATF_REQUIRE_MSG(nfds == expect,
+		"kevent() returns %d errno %d", nfds, errno);
+	close(kq);
+}
+
+/*
+ * Make sure that a full socket is not reported as writable by event APIs.
+ */
+ATF_TC_WITHOUT_HEAD(full_not_writable);
+ATF_TC_BODY(full_not_writable, tc)
+{
+	void *buf;
+	u_long sendspace;
+	int sv[2];
+
+	sendspace = getsendspace();
+	ATF_REQUIRE((buf = malloc(sendspace)) != NULL);
+	do_socketpair(sv);
+	ATF_REQUIRE(fcntl(sv[0], F_SETFL, O_NONBLOCK) != -1);
+	do {} while (send(sv[0], buf, sendspace, 0) == (ssize_t)sendspace);
+	ATF_REQUIRE(errno == EAGAIN);
+	ATF_REQUIRE(fcntl(sv[0], F_SETFL, 0) != -1);
+
+	check_writable(sv[0], 0);
+
+	/* Read some data and re-check. */
+	ATF_REQUIRE(read(sv[1], buf, sendspace / 2) == sendspace / 2);
+
+	check_writable(sv[0], 1);
+
+	free(buf);
+	close(sv[0]);
+	close(sv[1]);
+}
 
 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, getpeereid);
 	ATF_TP_ADD_TC(tp, send_0);
+	ATF_TP_ADD_TC(tp, full_not_writable);
 
 	return atf_no_error();
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202502102208.51AM8b5h039634>