Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 03 May 2026 23:09:19 +0000
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 476805133f57 - main - unix: Make sure we signal EOF on the write side when disconnecting
Message-ID:  <69f7d59f.24c32.3cabcabf@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by markj:

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

commit 476805133f5736c2c8638e41d2b5d8dd2c597f3a
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-05-03 15:46:22 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-05-03 21:51:49 +0000

    unix: Make sure we signal EOF on the write side when disconnecting
    
    Add a regression test.
    
    PR:             294014
    Reported by:    diizzy
    Reviewed by:    glebius
    MFC after:      1 week
    Fixes:          d15792780760 ("unix: new implementation of unix/stream & unix/seqpacket")
    Differential Revision:  https://reviews.freebsd.org/D56764
---
 sys/kern/uipc_usrreq.c       |  2 ++
 tests/sys/kern/unix_stream.c | 77 ++++++++++++++++++++++++++++++++++----------
 2 files changed, 62 insertions(+), 17 deletions(-)

diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index d56aac883d9c..8ff9822ee9eb 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -3159,6 +3159,8 @@ unp_soisdisconnected(struct socket *so)
 	so->so_state |= SS_ISDISCONNECTED;
 	so->so_state &= ~SS_ISCONNECTED;
 	so->so_rcv.uxst_peer = NULL;
+	selwakeuppri(&so->so_wrsel, PSOCK);
+	KNOTE_LOCKED(&so->so_snd.sb_sel->si_note, 0);
 	socantrcvmore_locked(so);
 }
 
diff --git a/tests/sys/kern/unix_stream.c b/tests/sys/kern/unix_stream.c
index 442b766ac885..df8dd1a15f85 100644
--- a/tests/sys/kern/unix_stream.c
+++ b/tests/sys/kern/unix_stream.c
@@ -109,6 +109,7 @@ typedef void check_func_t(struct check_ctx *);
 struct check_ctx {
 	check_func_t	*method;
 	int		sv[2];
+	int		kq;
 	bool		timeout;
 	union {
 		enum { SELECT_RD, SELECT_WR } select_what;
@@ -156,24 +157,47 @@ check_poll(struct check_ctx *ctx)
 }
 
 static void
-check_kevent(struct check_ctx *ctx)
+add_kevent(struct check_ctx *ctx)
 {
 	struct kevent kev;
-	int nfds, kq;
+	int kq, nfds;
+
+	if (ctx->kq <= 0) {
+		kq = kqueue();
+		ATF_REQUIRE(kq > 0);
+		ctx->kq = kq;
+	}
 
-	ATF_REQUIRE(kq = kqueue());
 	EV_SET(&kev, ctx->sv[0], ctx->kev_filter, EV_ADD, 0, 0, NULL);
-	nfds = kevent(kq, &kev, 1, NULL, 0, NULL);
+	nfds = kevent(ctx->kq, &kev, 1, NULL, 0, NULL);
 	ATF_REQUIRE_MSG(nfds == 0,
 	    "kevent() returns %d errno %d", nfds, errno);
-	nfds = kevent(kq, NULL, 0, &kev, 1, ctx->timeout ?
+}
+
+static void
+check_kevent(struct check_ctx *ctx)
+{
+	struct kevent kev;
+	int nfds;
+
+	nfds = kevent(ctx->kq, NULL, 0, &kev, 1, ctx->timeout ?
 	    &(struct timespec){.tv_nsec = 1000000} : NULL);
 	ATF_REQUIRE_MSG(nfds == ctx->nfds,
 	    "kevent() returns %d errno %d", nfds, errno);
-	ATF_REQUIRE(kev.ident == (uintptr_t)ctx->sv[0] &&
-	    kev.filter == ctx->kev_filter &&
-	    (kev.flags & ctx->kev_flags) == ctx->kev_flags);
-	close(kq);
+	if (nfds > 0) {
+		ATF_REQUIRE_EQ(kev.ident, (uintptr_t)ctx->sv[0]);
+		ATF_REQUIRE_EQ(kev.filter, ctx->kev_filter);
+		ATF_REQUIRE_EQ(kev.flags & ctx->kev_flags, ctx->kev_flags);
+	}
+	close(ctx->kq);
+	ctx->kq = -1;
+}
+
+static void
+add_and_check_kevent(struct check_ctx *ctx)
+{
+	add_kevent(ctx);
+	check_kevent(ctx);
 }
 
 static void
@@ -287,7 +311,7 @@ ATF_TC_WITHOUT_HEAD(full_writability_kevent);
 ATF_TC_BODY(full_writability_kevent, tc)
 {
 	struct check_ctx ctx = {
-		.method = check_kevent,
+		.method = add_and_check_kevent,
 		.kev_filter = EVFILT_WRITE,
 	};
 
@@ -312,7 +336,7 @@ ATF_TC_BODY(connected_writability, tc)
 	ctx.poll_events = POLLOUT | POLLWRNORM;
 	check_poll(&ctx);
 	ctx.kev_filter = EVFILT_WRITE;
-	check_kevent(&ctx);
+	add_and_check_kevent(&ctx);
 
 	close(ctx.sv[0]);
 	close(ctx.sv[1]);
@@ -333,13 +357,13 @@ ATF_TC_BODY(unconnected_writability, tc)
 	ctx.poll_events = POLLOUT | POLLWRNORM;
 	check_poll(&ctx);
 	ctx.kev_filter = EVFILT_WRITE;
-	check_kevent(&ctx);
+	add_and_check_kevent(&ctx);
 
 	close(ctx.sv[0]);
 }
 
-ATF_TC_WITHOUT_HEAD(peerclosed_writability);
-ATF_TC_BODY(peerclosed_writability, tc)
+ATF_TC_WITHOUT_HEAD(peerclosed_writability_level);
+ATF_TC_BODY(peerclosed_writability_level, tc)
 {
 	struct check_ctx ctx = {
 		.timeout = false,
@@ -355,6 +379,24 @@ ATF_TC_BODY(peerclosed_writability, tc)
 	check_poll(&ctx);
 	ctx.kev_filter = EVFILT_WRITE;
 	ctx.kev_flags = EV_EOF;
+	add_and_check_kevent(&ctx);
+
+	close(ctx.sv[0]);
+}
+
+ATF_TC_WITHOUT_HEAD(peerclosed_writability_edge);
+ATF_TC_BODY(peerclosed_writability_edge, tc)
+{
+	struct check_ctx ctx = {
+		.timeout = false,
+		.nfds = 1,
+	};
+
+	do_socketpair(ctx.sv);
+	ctx.kev_filter = EVFILT_WRITE;
+	ctx.kev_flags = EV_EOF;
+	add_kevent(&ctx);
+	close(ctx.sv[1]);
 	check_kevent(&ctx);
 
 	close(ctx.sv[0]);
@@ -384,7 +426,7 @@ ATF_TC_BODY(peershutdown_writability, tc)
 	 * and then this test will also expect EV_EOF in returned flags.
 	 */
 	ctx.kev_filter = EVFILT_WRITE;
-	check_kevent(&ctx);
+	add_and_check_kevent(&ctx);
 
 	close(ctx.sv[0]);
 	close(ctx.sv[1]);
@@ -463,7 +505,7 @@ ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_kevent);
 ATF_TC_BODY(peershutdown_wakeup_kevent, tc)
 {
 	peershutdown_wakeup(&(struct check_ctx){
-		.method = check_kevent,
+		.method = add_and_check_kevent,
 		.kev_filter = EVFILT_READ,
 		.kev_flags = EV_EOF,
 	});
@@ -525,7 +567,8 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, full_writability_select);
 	ATF_TP_ADD_TC(tp, full_writability_poll);
 	ATF_TP_ADD_TC(tp, full_writability_kevent);
-	ATF_TP_ADD_TC(tp, peerclosed_writability);
+	ATF_TP_ADD_TC(tp, peerclosed_writability_level);
+	ATF_TP_ADD_TC(tp, peerclosed_writability_edge);
 	ATF_TP_ADD_TC(tp, peershutdown_writability);
 	ATF_TP_ADD_TC(tp, peershutdown_readability);
 	ATF_TP_ADD_TC(tp, peershutdown_wakeup_select);


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69f7d59f.24c32.3cabcabf>