git: afeb885b4ae4 - main - linux: Preserve partial results from recvmmsg()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 28 Oct 2026 15:25:27 UTC
The branch main has been updated by pouria:
URL: https://cgit.FreeBSD.org/src/commit/?id=afeb885b4ae41357a648f547d3835a5e0dcde81e
commit afeb885b4ae41357a648f547d3835a5e0dcde81e
Author: Vladimir Grebenshchikov <vova@zote.me>
AuthorDate: 2026-10-21 22:14:33 +0000
Commit: Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
CommitDate: 2026-10-28 15:15:51 +0000
linux: Preserve partial results from recvmmsg()
linux_recvmmsg_common() currently returns the error from the next
recvmsg() attempt even when one or more datagrams have already been
received and copied to userspace.
This is especially visible with non-blocking UDP sockets. After
receiving the first datagram, the next iteration commonly returns
EAGAIN. The syscall then reports EAGAIN instead of the number of
messages already stored in the mmsghdr array, causing applications to
discard successfully received packets.
This differs from Linux recvmmsg() semantics, where an error encountered
after receiving at least one message is deferred and the number of
received messages is returned.
Return the accumulated datagram count and clear the error whenever at
least one message was received. Preserve the original error when no
messages were received.
This fixes packet loss in applications such as wireguard-go, whose
non-blocking receive path uses recvmmsg() for batches of UDP packets.
In the observed failure, WireGuard handshake responses reached the UDP
socket, but a subsequent EAGAIN caused recvmmsg() to hide the received
response and the handshake timed out.
Reviewed by: kib
Pull Request: https://github.com/freebsd/freebsd-src/pull/2484
Differential Revision: https://reviews.freebsd.org/D60961
---
sys/compat/linux/linux_socket.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 9c94079e0e0f..f2ed584d1f4c 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -2053,8 +2053,10 @@ linux_recvmmsg_common(struct thread *td, l_int s, struct l_mmsghdr *msg,
if (bsd_msg.msg_flags & MSG_OOB)
break;
}
- if (error == 0)
+ if (datagrams != 0) {
td->td_retval[0] = datagrams;
+ error = 0;
+ }
fdrop(fp, td);
return (error);
}