Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 Oct 2025 17:59:31 GMT
From:      Colin Percival <cperciva@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: b05f153cd220 - releng/15.0 - unix/stream: repair SO_SNDTIMEO
Message-ID:  <202510171759.59HHxVOl086065@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch releng/15.0 has been updated by cperciva:

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

commit b05f153cd22081bbcbcf41439219ffea6750ba46
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-10-15 00:29:31 +0000
Commit:     Colin Percival <cperciva@FreeBSD.org>
CommitDate: 2025-10-17 17:58:38 +0000

    unix/stream: repair SO_SNDTIMEO
    
    The send operations are waiting on the peer's socket buffer, but we shall
    use our timeout value.  Provide a test for that.
    
    Approved by:    re (cperciva)
    Reported by:            phk
    Reviewed by:            asomers
    Differential Revision:  https://reviews.freebsd.org/D53081
    Fixes:                  d15792780760ef94647af9b377b5f0a80e1826bc
    
    (cherry picked from commit ead721935251ab5640ea736d4269814b7f9d2f64)
    (cherry picked from commit bbfaff26bf365126cb4d38fda99a2100a256d9bd)
---
 sys/kern/uipc_usrreq.c       | 20 ++++++++++++++++++--
 tests/sys/kern/unix_stream.c | 27 +++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 340d84666459..c5fc1e84ce3f 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -1069,6 +1069,21 @@ uipc_stream_sbspace(struct sockbuf *sb)
 	return (min(space, mbspace));
 }
 
+/*
+ * UNIX version of generic sbwait() for writes.  We wait on peer's receive
+ * buffer, using our timeout.
+ */
+static int
+uipc_stream_sbwait(struct socket *so, sbintime_t timeo)
+{
+	struct sockbuf *sb = &so->so_rcv;
+
+	SOCK_RECVBUF_LOCK_ASSERT(so);
+	sb->sb_flags |= SB_WAIT;
+	return (msleep_sbt(&sb->sb_acc, SOCK_RECVBUF_MTX(so), PSOCK | PCATCH,
+	    "sbwait", timeo, 0, 0));
+}
+
 static int
 uipc_sosend_stream_or_seqpacket(struct socket *so, struct sockaddr *addr,
     struct uio *uio0, struct mbuf *m, struct mbuf *c, int flags,
@@ -1203,7 +1218,8 @@ restart:
 				error = EWOULDBLOCK;
 				goto out4;
 			}
-			if ((error = sbwait(so2, SO_RCV)) != 0) {
+			if ((error = uipc_stream_sbwait(so2,
+			    so->so_snd.sb_timeo)) != 0) {
 				SOCK_RECVBUF_UNLOCK(so2);
 				goto out4;
 			} else
@@ -2397,7 +2413,7 @@ uipc_sendfile_wait(struct socket *so, off_t need, int *space)
 		}
 		if (!sockref)
 			soref(so2);
-		error = sbwait(so2, SO_RCV);
+		error = uipc_stream_sbwait(so2, so->so_snd.sb_timeo);
 		if (error == 0 &&
 		    __predict_false(sb->sb_state & SBS_CANTRCVMORE))
 			error = EPIPE;
diff --git a/tests/sys/kern/unix_stream.c b/tests/sys/kern/unix_stream.c
index 49d621dc5b0a..442b766ac885 100644
--- a/tests/sys/kern/unix_stream.c
+++ b/tests/sys/kern/unix_stream.c
@@ -1,6 +1,7 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
+ * Copyright (c) 2025 Gleb Smirnoff <glebius@FreeBSD.org>
  * Copyright (c) 2018 Alan Somers
  *
  * Redistribution and use in source and binary forms, with or without
@@ -30,6 +31,7 @@
 #include <sys/event.h>
 #include <sys/select.h>
 #include <sys/sysctl.h>
+#include <sys/time.h>
 #include <sys/un.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -490,6 +492,30 @@ ATF_TC_BODY(ourshutdown_kevent, tc)
 	close(sv[1]);
 }
 
+ATF_TC_WITHOUT_HEAD(SO_SNDTIMEO);
+ATF_TC_BODY(SO_SNDTIMEO, tc)
+{
+	struct timespec tp1, tp2, rtp, sleep = { .tv_nsec = 100000000 };
+	int sv[2];
+	char buf[10];
+
+	full_socketpair(sv);
+	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDTIMEO,
+	  &(struct timeval){ .tv_usec = sleep.tv_nsec / 1000 },
+	  sizeof(struct timeval)));
+	ATF_REQUIRE_EQ(0, clock_gettime(CLOCK_MONOTONIC_PRECISE, &tp1));
+	ATF_REQUIRE_EQ(-1, send(sv[0], buf, sizeof(buf), 0));
+	ATF_REQUIRE(errno == EAGAIN);
+	ATF_REQUIRE_EQ(0, clock_gettime(CLOCK_MONOTONIC_PRECISE, &tp2));
+	timespecsub(&tp2, &tp1, &rtp);
+	ATF_REQUIRE(timespeccmp(&rtp, &sleep, >=));
+	ATF_REQUIRE_EQ(sizeof(buf), recv(sv[1], buf, sizeof(buf), 0));
+	ATF_REQUIRE_EQ(sizeof(buf), send(sv[0], buf, sizeof(buf), 0));
+
+	close(sv[0]);
+	close(sv[1]);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, getpeereid);
@@ -506,6 +532,7 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, peershutdown_wakeup_poll);
 	ATF_TP_ADD_TC(tp, peershutdown_wakeup_kevent);
 	ATF_TP_ADD_TC(tp, ourshutdown_kevent);
+	ATF_TP_ADD_TC(tp, SO_SNDTIMEO);
 
 	return atf_no_error();
 }



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