[Bug 295009] UDP receive with zero-size buffer immediately returns, no wait, no EAGAIN
Date: Mon, 04 May 2026 15:45:22 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=295009
Bug ID: 295009
Summary: UDP receive with zero-size buffer immediately returns,
no wait, no EAGAIN
Product: Base System
Version: 15.0-RELEASE
Hardware: Any
OS: Any
Status: New
Severity: Affects Many People
Priority: ---
Component: kern
Assignee: bugs@FreeBSD.org
Reporter: thierry@lelegard.fr
On FreeBSD 15.0-RELEASE-p8, receiving a UDP datagram using recv(), recvfrom(),
or recvmsg() with a zero-size data buffer immediately returns with value zero,
even when no datagram is sent, even when the socket is in non-blocking mode.
According to the POSIX spec and the FreeBSD man pages, when zero is specified
as reception buffer size, the correct behaviour should be:
- In blocking mode: wait for a datagram, return zero, optionally report the
truncation of the message in flags.
- In non-blocking mode, when no message is immediately available, return -1
and set errno to EAGAIN.
Other operating systems:
- macOS 26.4.1 behaves as FreeBSD. The bug is probably in their common roots.
- Linux 7.0: expected POSIX behaviour.
The following code reproduces the problem. It opens a UDP socket, binds it to
127.0.0.1:1234, and receives a message (typically a text string to display).
There are two parameters: receive buffer size and optional non-blocking mode.
Syntax: udpzero [bufsize [-n]]
bufsize : receive buffer size, default: 256
-n : non-blocking
Sample command to send a 4-byte message using bash:
echo -n "abcd" >/dev/udp/127.0.0.1/1234
On FreeBSD 15.0-RELEASE-p8 and macOS 26.4.1:
$ ./udpzero
receive buffer size: 256, blocking mode
[... wait for a message ...]
received size: 4, data: "abcd"
$
$ ./udpzero 10 -n
receive buffer size: 10, non-blocking mode
recv: Resource temporarily unavailable
$
$ ./udpzero 0
receive buffer size: 0, blocking mode
received size: 0, data: ""
$
$ ./udpzero 0 -n
receive buffer size: 0, non-blocking mode
received size: 0, data: ""
On Linux 7.0 (Ubuntu 26.04):
$ ./udpzero
receive buffer size: 256, blocking mode
[... wait for a message ...]
received size: 4, data: "abcd"
$
$ ./udpzero 10 -n
receive buffer size: 10, non-blocking mode
recv: Resource temporarily unavailable
$
$ ./udpzero 0
receive buffer size: 0, blocking mode
[... wait for a message ...]
received size: 0, data: ""
$
$ ./udpzero 0 -n
receive buffer size: 0, non-blocking mode
recv: Resource temporarily unavailable
-----------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
void check(int cond, const char* message)
{
if (!cond) {
perror(message);
exit(EXIT_FAILURE);
}
}
int main(int argc, char* argv[])
{
const int bufsize = argc < 2 ? 256 : atoi(argv[1]);
const int nonblock = argc >= 3 && strcmp(argv[2], "-n") == 0;
printf("receive buffer size: %d, %sblocking mode\n", bufsize, nonblock ?
"non-" : "");
char* data = malloc(bufsize);
check(data != NULL, "malloc");
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
check(sock >= 0, "socket");
if (nonblock) {
int flags = fcntl(sock, F_GETFL, 0);
check(flags != -1, "fcntl");
flags = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
check(flags != -1, "fcntl");
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(0x7F000001); // 127.0.0.1
addr.sin_port = htons(1234);
int status = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
check(status == 0, "bind");
socklen_t len = sizeof(addr);
ssize_t insize = recvfrom(sock, data, bufsize, 0, (struct sockaddr*)&addr,
&len);
check(insize >= 0, "recv");
printf("received size: %ld, data: \"%.*s\"\n", insize, (int)insize, data);
close(sock);
return EXIT_SUCCESS;
}
--
You are receiving this mail because:
You are the assignee for the bug.