Skip site navigation (1)Skip section navigation (2)



index | | raw e-mail

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D295009

            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 ze=
ro,
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 specifi=
ed
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 root=
s.
- 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 mod=
e.

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 =3D argc < 2 ? 256 : atoi(argv[1]);
    const int nonblock =3D argc >=3D 3 && strcmp(argv[2], "-n") =3D=3D 0;
    printf("receive buffer size: %d, %sblocking mode\n", bufsize, nonblock ?
"non-" : "");

    char* data =3D malloc(bufsize);
    check(data !=3D NULL, "malloc");

    int sock =3D socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    check(sock >=3D 0, "socket");

    if (nonblock) {
        int flags =3D fcntl(sock, F_GETFL, 0);
        check(flags !=3D -1, "fcntl");
        flags =3D fcntl(sock, F_SETFL, flags | O_NONBLOCK);
        check(flags !=3D -1, "fcntl");
    }

    struct sockaddr_in addr;
    addr.sin_family =3D AF_INET;
    addr.sin_addr.s_addr =3D htonl(0x7F000001); // 127.0.0.1
    addr.sin_port =3D htons(1234);
    int status =3D bind(sock, (struct sockaddr*)&addr, sizeof(addr));
    check(status =3D=3D 0, "bind");

    socklen_t len =3D sizeof(addr);
    ssize_t insize =3D recvfrom(sock, data, bufsize, 0, (struct sockaddr*)&=
addr,
&len);
    check(insize >=3D 0, "recv");
    printf("received size: %ld, data: \"%.*s\"\n", insize, (int)insize, dat=
a);

    close(sock);
    return EXIT_SUCCESS;
}

--=20
You are receiving this mail because:
You are the assignee for the bug.=


home | help