The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=60d5a4216b3479a2d62eb65f2cb03b799546dcbb
commit 60d5a4216b3479a2d62eb65f2cb03b799546dcbb Author: Gleb Smirnoff <gleb...@freebsd.org> AuthorDate: 2025-09-02 20:34:12 +0000 Commit: Gleb Smirnoff <gleb...@freebsd.org> CommitDate: 2025-09-02 20:34:12 +0000 unix/stream: fix EVFILT_WRITE after we did shutdown(2) When fixing bug 286692, the change eafe5967ac558, that fixed a case when peer side does close(), also had regressed a case when our side does shutdown(SHUT_WR). These actually are two independent code paths, and the eafe5967ac558 shouldn't have touched the second block. The removal of 'kn->kn_flags |= EV_EOF' was incorrect and the statement on original behavior in the commit message was also incorrect. Do not add back so_error setting, since I failed to find a test case that would return anything but 0 in kevent.fflags when run on stable/14. This was found with help of https://github.com/tokio-rs/mio. Add a test case into our test suite for that. Fixes: eafe5967ac558de142d91660e18e9238289890e3 Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D52327 --- sys/kern/uipc_usrreq.c | 4 +--- tests/sys/kern/unix_stream.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 19870e989437..6138e543fae7 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1807,9 +1807,7 @@ uipc_filt_sowrite(struct knote *kn, long hint) kn->kn_data = uipc_stream_sbspace(&so2->so_rcv); if (so2->so_rcv.sb_state & SBS_CANTRCVMORE) { - /* - * XXXGL: maybe kn->kn_flags |= EV_EOF ? - */ + kn->kn_flags |= EV_EOF; return (1); } else if (kn->kn_sfflags & NOTE_LOWAT) return (kn->kn_data >= kn->kn_sdata); diff --git a/tests/sys/kern/unix_stream.c b/tests/sys/kern/unix_stream.c index bb811f78f620..49d621dc5b0a 100644 --- a/tests/sys/kern/unix_stream.c +++ b/tests/sys/kern/unix_stream.c @@ -467,6 +467,29 @@ ATF_TC_BODY(peershutdown_wakeup_kevent, tc) }); } +ATF_TC_WITHOUT_HEAD(ourshutdown_kevent); +ATF_TC_BODY(ourshutdown_kevent, tc) +{ + struct kevent kev; + int sv[2], kq; + + do_socketpair(sv); + ATF_REQUIRE(kq = kqueue()); + + EV_SET(&kev, sv[1], EVFILT_WRITE, EV_ADD, 0, 0, NULL); + ATF_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0); + + ATF_REQUIRE(shutdown(sv[1], SHUT_WR) == 0); + + ATF_REQUIRE(kevent(kq, NULL, 0, &kev, 1, NULL) == 1); + ATF_REQUIRE(kev.ident == (uintptr_t)sv[1] && + kev.filter == EVFILT_WRITE && + kev.flags == EV_EOF); + + close(sv[0]); + close(sv[1]); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, getpeereid); @@ -482,6 +505,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, peershutdown_wakeup_select); ATF_TP_ADD_TC(tp, peershutdown_wakeup_poll); ATF_TP_ADD_TC(tp, peershutdown_wakeup_kevent); + ATF_TP_ADD_TC(tp, ourshutdown_kevent); return atf_no_error(); }