[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.