[Bug 279444] rtnetlink: recv(4) with MSG_DONTWAIT returns EAGAIN.
Date: Fri, 31 May 2024 22:10:39 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=279444
Bug ID: 279444
Summary: rtnetlink: recv(4) with MSG_DONTWAIT returns EAGAIN.
Product: Base System
Version: 14.0-RELEASE
Hardware: Any
OS: Any
Status: New
Severity: Affects Only Me
Priority: ---
Component: kern
Assignee: bugs@FreeBSD.org
Reporter: gnats@duck.com
When reading the title, you're probably thinking, “well, yeah, that's how it
should work.” and while I agree with you, the musl developers don't! [1]
(Though, it's really not their fault.) While testing the glibc netlink
shenanigans bug #279012, I also decided to test musl. In which, I found that
because musl does a recv(2) (which is technically a recvfrom(2)) with
MSG_DONTWAIT on a netlink socket, it always returns -1 (EAGAIN or EWOULDBLOCK).
[1] That said, you can actually get it to work intermittently if you supply
some latency (e.g., strace); however, like mentioned, this tends to be
unpredictable. I imagine that the Linux kernel is not faster than us here, but
rather doing something clever, and we have yet to implement such trickery as
well. I'll attach some code that reproduces the issue. This can be compiled on
the linuxulator and freebsd to the same effect, which implies this problem
resides in the base netlink code.
#include <stdio.h>
#include <string.h>
#ifdef __FreeBSD__
#include <netlink/netlink.h>
#include <netlink/netlink_route.h>
#else
#include <linux/rtnetlink.h>
#endif
#include <arpa/inet.h>
int main(void) {
int fd;
fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
if (fd < 0) return -1;
unsigned int seq = 1;
int type = RTM_GETLINK;
int af = AF_UNSPEC;
struct nlmsghdr * h;
union {
uint8_t buf[8192];
struct {
struct nlmsghdr nlh;
struct rtgenmsg g;
}
req;
struct nlmsghdr reply;
}
u;
int r, ret;
memset( & u.req, 0, sizeof(u.req));
u.req.nlh.nlmsg_len = sizeof(u.req);
u.req.nlh.nlmsg_type = type;
u.req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
u.req.nlh.nlmsg_seq = seq;
u.req.g.rtgen_family = af;
r = send(fd, & u.req, sizeof(u.req), 0);
if (r < 0) return r;
do {
r = recv(fd, u.buf, sizeof(u.buf), MSG_DONTWAIT);
if (r <= 0)
printf("bad recv: %d\n", r);
else
printf("good recv: %d\n", r);
} while (r <= 0);
return 0;
}
[1] https://elixir.bootlin.com/musl/latest/source/src/network/netlink.c#L31
--
You are receiving this mail because:
You are the assignee for the bug.