Behavioral difference between Linux and FreeBSD poll()
- Reply: Bob Bishop : "Re: Behavioral difference between Linux and FreeBSD poll()"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 04 Jun 2025 08:04:49 UTC
Hey hackers. I was debugging two seemingly unrelated issues regarding busy-looping in D-Bus and Qt applications and bumped into a common root problem - our poll() implementation doesn't return POLLERR when callers expect that. The standard is indeed blurry on this topic [1] and does not specify when exactly POLLERR should be delivered. Here is a program that demonstrates the difference: https://arrowd.name/poll.c On Linux I only see 28 (POLLOUT | POLLERR | POLLHUP) 28 (POLLOUT | POLLERR | POLLHUP) ... and on FreeBSD I get 20 (POLLOUT|POLLWRNORM|POLLHUP) 16 (POLLHUP) 16 (POLLHUP) ... Now here are places in the code expecting POLLERR: - Qt [2] + [3], [4] - D-Bus [5] On FreeBSD these places result in busy-loop, because poll() returns immediately, but the caller code does not handle the revents = POLLHUP case properly and gets back to calling poll() again. My question is what would be a correct way to fix these issues. Should I patch poll() consumers to better handle POLLHUP or should we rather fix the kernel side to return POLLERR? Grepping through the src reveals that we have places, where calling code requests POLLERR in .events, which makes me think that it is the kernel that should be fixed. But I'm not a real kernel hacker. P.S. Interestingly, the standard says that POLLOUT and POLLHUP are mutually exclusive, but both Linux and FreeBSD send them together. [1] https://pubs.opengroup.org/onlinepubs/009696799/functions/poll.html [2] https://github.com/qt/qtbase/blob/4db3961ee140867e14f8e1d20173e85060bc6c50/src/corelib/kernel/qeventdispatcher_glib.cpp#L60 [3] https://github.com/qt/qtbase/blob/4db3961ee140867e14f8e1d20173e85060bc6c50/src/corelib/kernel/qeventdispatcher_glib.cpp#L437 [4] https://github.com/qt/qtbase/blob/4db3961ee140867e14f8e1d20173e85060bc6c50/src/network/socket/qnativesocketengine_unix.cpp#L1383 [5] https://gitlab.freedesktop.org/dbus/dbus/-/blob/6bba6c58c5635bc123cb565ee1aac0f12cd980d3/dbus/dbus-transport-socket.c?page=2#L1207-1212