Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Jun 2025 12:49:44 +0100
From:      Bob Bishop <rb@gid.co.uk>
To:        Gleb Popov <arrowd@FreeBSD.org>
Cc:        freebsd-hackers <freebsd-hackers@FreeBSD.org>
Subject:   Re: Behavioral difference between Linux and FreeBSD poll()
Message-ID:  <B9BBB7F3-6984-4180-85D1-D5298A278F13@gid.co.uk>
In-Reply-To: <CALH631mtKV=0z0Pj83GZ%2BQE08V%2BeT4iJJcj3ov_V4nsuxPfSFQ@mail.gmail.com>
References:  <CALH631mtKV=0z0Pj83GZ%2BQE08V%2BeT4iJJcj3ov_V4nsuxPfSFQ@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

Hi,

> On 4 Jun 2025, at 09:04, Gleb Popov <arrowd@FreeBSD.org> wrote:
> 
> 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.

Well strictly the only thing that is unclear in the standard is whether it’s OK to return POLLERR with POLLHUP.

> 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?

Consumers looking for disconnexion should test POLLHUP not 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.

... which is clearly a bug; but consumers ought to ignore POLLOUT if they see POLLHUP.

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

--
Bob Bishop
rb@gid.co.uk







Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?B9BBB7F3-6984-4180-85D1-D5298A278F13>