Index | Thread | Search

From:
yaydn@protonmail.com
Subject:
Re: Qt6: Fix poll() busy-loop on socket close with POLLOUT
To:
Rafael Sadowski <rafael@sizeofvoid.org>
Cc:
"ports@openbsd.org" <ports@openbsd.org>
Date:
Tue, 05 Aug 2025 06:00:02 +0000

Download raw body.

Thread
På mandag 4. august 2025 kl. 17:32, Rafael Sadowski
<rafael@sizeofvoid.org> skrev:

> sys/kern/sys_generic.c:
> if (pl[i].events != 0 && pl[i].events != POLLOUT)
> DPRINTFN(0, "weird events %x\n", pl[i].events);
>
> Looks like we have the same behavior as FreeBSD:
>
> https://codereview.qt-project.org/c/qt/qtbase/+/651677
>
> "On FreeBSD when asked for POLLOUT the poll() syscall returns only POLLHUP to
> signify the fact that the other side closed the connection. It never sends
> POLLERR for EOF cases, which results in a busy-loop inside the Glib dispatcher:
>
> - poll() returns immediately with POLLHUP for a closed socket
> - socketNotifierSourceCheck() does not detect it, because
> events = POLLOUT | POLLERR and we get .revents = POLLHUP.
> The (events & revents != 0) condition evaluates to false
> - the code decides there is nothing to do and a new iteration starts"
>
> A similar issue in dbus code: https://gitlab.freedesktop.org/dbus/dbus/-/merge_requests/526
>
> @Antoine Maybe we should patch dbus too?
>
> OK?
>


Tested on current/amd64.

cd /usr/ports/ && patch -l -p1 -E < /tmp/qt6-qtbase-p3.patch
cd /usr/ports/x11/qt6/qtbase/ && make update clean && make distclean

Built fine.

Looks good.

Hope this helps.

Well wishes and have a good one. Happy porting!


> diff --git a/x11/qt6/qtbase/Makefile b/x11/qt6/qtbase/Makefile
> index 3788dfa293f..9c7df648b55 100644
> --- a/x11/qt6/qtbase/Makefile
> +++ b/x11/qt6/qtbase/Makefile
> @@ -4,7 +4,7 @@ COMMENT-main = C++ general-purpose toolkit
> COMMENT-global = global Qt6 documentation internals
> COMMENT-mysql = MySQL plugin for Qt6
> COMMENT-psql = PostgresSQL plugin for Qt6
> -REVISION-main = 2
> +REVISION-main = 3
>
> PKGSPEC-main = qt6-qtbase-${QT6_PKGSPEC}
>
> diff --git a/x11/qt6/qtbase/patches/patch-src_corelib_kernel_qeventdispatcher_glib_cpp b/x11/qt6/qtbase/patches/patch-src_corelib_kernel_qeventdispatcher_glib_cpp
> new file mode 100644
> index 00000000000..45ee0cfff2d
> --- /dev/null
> +++ b/x11/qt6/qtbase/patches/patch-src_corelib_kernel_qeventdispatcher_glib_cpp
> @@ -0,0 +1,18 @@
> +https://codereview.qt-project.org/c/qt/qtbase/+/651677
> +
> +Index: src/corelib/kernel/qeventdispatcher_glib.cpp
> +--- src/corelib/kernel/qeventdispatcher_glib.cpp.orig
> ++++ src/corelib/kernel/qeventdispatcher_glib.cpp
> +@@ -434,10 +434,10 @@ void QEventDispatcherGlib::registerSocketNotifier(QSoc
> + p->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
>
> + break;
> + case QSocketNotifier::Write:
> +- p->pollfd.events = G_IO_OUT | G_IO_ERR;
>
> ++ p->pollfd.events = G_IO_OUT | G_IO_HUP | G_IO_ERR;
>
> + break;
> + case QSocketNotifier::Exception:
> +- p->pollfd.events = G_IO_PRI | G_IO_ERR;
>
> ++ p->pollfd.events = G_IO_PRI | G_IO_HUP | G_IO_ERR;
>
> + break;
> + }
> + p->socketNotifier = notifier;
>
> diff --git a/x11/qt6/qtbase/patches/patch-src_network_socket_qnativesocketengine_unix_cpp b/x11/qt6/qtbase/patches/patch-src_network_socket_qnativesocketengine_unix_cpp
> new file mode 100644
> index 00000000000..20af6817dad
> --- /dev/null
> +++ b/x11/qt6/qtbase/patches/patch-src_network_socket_qnativesocketengine_unix_cpp
> @@ -0,0 +1,14 @@
> +https://codereview.qt-project.org/c/qt/qtbase/+/651677
> +
> +Index: src/network/socket/qnativesocketengine_unix.cpp
> +--- src/network/socket/qnativesocketengine_unix.cpp.orig
> ++++ src/network/socket/qnativesocketengine_unix.cpp
> +@@ -1379,7 +1379,7 @@ int QNativeSocketEnginePrivate::nativeSelect(QDeadline
> + }
> +
> + static const short read_flags = POLLIN | POLLHUP | POLLERR;
> +- static const short write_flags = POLLOUT | POLLERR;
> ++ static const short write_flags = POLLOUT | POLLHUP | POLLERR;
> +
> + *selectForRead = ((pfd.revents & read_flags) != 0);
> + *selectForWrite = ((pfd.revents & write_flags) != 0);