From 8f9222db3b5976ac0977b9ed5f27744c24bd982e Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Wed, 27 Jan 2021 16:18:11 +0200 Subject: [PATCH] QEventDispatcherGlib: do not omit active notifiers on source dispatching It is quite common for a socket notifier to be disabled in a slot connected to its activated() signal. But the event dispatcher did not update the position in the list of registered notifiers, which caused the next notifier to be omitted. Of course, on the next iteration of the event loop, the omitted notifier would fire again, but this reduced the scalability of applications that use a large number of sockets. To solve the problem, we update the current position in the list when a notifier becomes unregistered. Change-Id: I6565bf23500d9e38ce84b34784d89d227fa166e1 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/kernel/qeventdispatcher_glib.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 59c937362b..86f6b0b4aa 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -62,6 +62,7 @@ struct GSocketNotifierSource { GSource source; QList pollfds; + int activeNotifierPos; }; static gboolean socketNotifierSourcePrepare(GSource *, gint *timeout) @@ -100,8 +101,9 @@ static gboolean socketNotifierSourceDispatch(GSource *source, GSourceFunc, gpoin QEvent event(QEvent::SockAct); GSocketNotifierSource *src = reinterpret_cast(source); - for (int i = 0; i < src->pollfds.count(); ++i) { - GPollFDWithQSocketNotifier *p = src->pollfds.at(i); + for (src->activeNotifierPos = 0; src->activeNotifierPos < src->pollfds.count(); + ++src->activeNotifierPos) { + GPollFDWithQSocketNotifier *p = src->pollfds.at(src->activeNotifierPos); if ((p->pollfd.revents & p->pollfd.events) != 0) QCoreApplication::sendEvent(p->socketNotifier, &event); @@ -501,6 +503,10 @@ void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier) d->socketNotifierSource->pollfds.removeAt(i); delete p; + // Keep a position in the list for the next item. + if (i <= d->socketNotifierSource->activeNotifierPos) + --d->socketNotifierSource->activeNotifierPos; + return; } }