git: bc7ee0b52a8d - main - tests/unix_stream: add test that checks a full socket isn't writable
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 10 Feb 2025 22:08:37 UTC
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();
}