From c3defef04221cbad459c76b4d3660ea1ac4108c8 Mon Sep 17 00:00:00 2001 From: Rex Dieter Date: Oct 30 2009 12:01:23 +0000 Subject: - use upstream qeventdispatcher_glib_fix.diff (kde#210171) --- diff --git a/qeventdispatcher_glib_fix.diff b/qeventdispatcher_glib_fix.diff new file mode 100644 index 0000000..482c0a3 --- /dev/null +++ b/qeventdispatcher_glib_fix.diff @@ -0,0 +1,282 @@ +commit 063bded33b417cdf92fd51366fc7fdb06dea00ba +Author: Bradley T. Hughes +Date: Wed Sep 23 13:51:17 2009 +0200 + + Fix regressions in qeventloop, qtimer, and qsocketnotifier autotests + + Commit ed375675d4a4f6fd63edeb242e23c87b3de4be6f triggers a behavior in + Glib's mainloop implementation where some event sources are not + "serviced" every iteration of the mainloop context. This breaks an + invariant that many tests relied on, so we need to solve the problem. + + The invariant is that a newly added timer that would normally fire on + the next pass of the event loop (liker a zero timer) SHOULD actually + fire. We do this by registering 2 timer event sources with Glib's + mainloop: one normal priority source and one idle priority source. The + idle priority source is the one that will send events most of the + time, with the normal priority one taking over only when + processEvents() is called manually. + + Task-number: QT-877 + Reviewed-by: jbache + Reviewed-by: thiago + Reviewed-by: denis + (cherry picked from commit d0d0fdb8e46351b4ab8492de31e5363ef6662b57) + (cherry picked from commit 0ed23e95fa756fd851f509a565f91ab43fc30449) + +diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp +index 87e9728..7f6dbb6 100644 +--- a/src/corelib/kernel/qeventdispatcher_glib.cpp ++++ b/src/corelib/kernel/qeventdispatcher_glib.cpp +@@ -127,16 +127,11 @@ struct GTimerSource + GSource source; + QTimerInfoList timerList; + QEventLoop::ProcessEventsFlags processEventsFlags; ++ bool runWithIdlePriority; + }; + +-static gboolean timerSourcePrepare(GSource *source, gint *timeout) ++static gboolean timerSourcePrepareHelper(GTimerSource *src, gint *timeout) + { +- gint dummy; +- if (!timeout) +- timeout = &dummy; +- +- GTimerSource *src = reinterpret_cast(source); +- + timeval tv = { 0l, 0l }; + if (!(src->processEventsFlags & QEventLoop::X11ExcludeTimers) && src->timerList.timerWait(tv)) + *timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); +@@ -146,10 +141,8 @@ static gboolean timerSourcePrepare(GSource *source, gint *timeout) + return (*timeout == 0); + } + +-static gboolean timerSourceCheck(GSource *source) ++static gboolean timerSourceCheckHelper(GTimerSource *src) + { +- GTimerSource *src = reinterpret_cast(source); +- + if (src->timerList.isEmpty() + || (src->processEventsFlags & QEventLoop::X11ExcludeTimers)) + return false; +@@ -160,9 +153,35 @@ static gboolean timerSourceCheck(GSource *source) + return true; + } + ++static gboolean timerSourcePrepare(GSource *source, gint *timeout) ++{ ++ gint dummy; ++ if (!timeout) ++ timeout = &dummy; ++ ++ GTimerSource *src = reinterpret_cast(source); ++ if (src->runWithIdlePriority) { ++ if (timeout) ++ *timeout = -1; ++ return false; ++ } ++ ++ return timerSourcePrepareHelper(src, timeout); ++} ++ ++static gboolean timerSourceCheck(GSource *source) ++{ ++ GTimerSource *src = reinterpret_cast(source); ++ if (src->runWithIdlePriority) ++ return false; ++ return timerSourceCheckHelper(src); ++} ++ + static gboolean timerSourceDispatch(GSource *source, GSourceFunc, gpointer) + { +- (void) reinterpret_cast(source)->timerList.activateTimers(); ++ GTimerSource *timerSource = reinterpret_cast(source); ++ timerSource->runWithIdlePriority = true; ++ (void) timerSource->timerList.activateTimers(); + return true; // ??? don't remove, right again? + } + +@@ -175,6 +194,53 @@ static GSourceFuncs timerSourceFuncs = { + NULL + }; + ++struct GIdleTimerSource ++{ ++ GSource source; ++ GTimerSource *timerSource; ++}; ++ ++static gboolean idleTimerSourcePrepare(GSource *source, gint *timeout) ++{ ++ GIdleTimerSource *idleTimerSource = reinterpret_cast(source); ++ GTimerSource *timerSource = idleTimerSource->timerSource; ++ if (!timerSource->runWithIdlePriority) { ++ // Yield to the normal priority timer source ++ if (timeout) ++ *timeout = -1; ++ return false; ++ } ++ ++ return timerSourcePrepareHelper(timerSource, timeout); ++} ++ ++static gboolean idleTimerSourceCheck(GSource *source) ++{ ++ GIdleTimerSource *idleTimerSource = reinterpret_cast(source); ++ GTimerSource *timerSource = idleTimerSource->timerSource; ++ if (!timerSource->runWithIdlePriority) { ++ // Yield to the normal priority timer source ++ return false; ++ } ++ return timerSourceCheckHelper(timerSource); ++} ++ ++static gboolean idleTimerSourceDispatch(GSource *source, GSourceFunc, gpointer) ++{ ++ GTimerSource *timerSource = reinterpret_cast(source)->timerSource; ++ (void) timerSourceDispatch(&timerSource->source, 0, 0); ++ return true; ++} ++ ++static GSourceFuncs idleTimerSourceFuncs = { ++ idleTimerSourcePrepare, ++ idleTimerSourceCheck, ++ idleTimerSourceDispatch, ++ NULL, ++ NULL, ++ NULL ++}; ++ + struct GPostEventSource + { + GSource source; +@@ -235,14 +301,15 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) + g_main_context_ref(mainContext); + } else { + QCoreApplication *app = QCoreApplication::instance(); +- if (app && QThread::currentThread() == app->thread()) { +- mainContext = g_main_context_default(); +- g_main_context_ref(mainContext); +- } else { +- mainContext = g_main_context_new(); +- } ++ if (app && QThread::currentThread() == app->thread()) { ++ mainContext = g_main_context_default(); ++ g_main_context_ref(mainContext); ++ } else { ++ mainContext = g_main_context_new(); ++ } + } + ++ // setup post event source + postEventSource = reinterpret_cast(g_source_new(&postEventSourceFuncs, + sizeof(GPostEventSource))); + postEventSource->serialNumber = 1; +@@ -257,14 +324,21 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) + g_source_set_can_recurse(&socketNotifierSource->source, true); + g_source_attach(&socketNotifierSource->source, mainContext); + +- // setup timerSource ++ // setup normal and idle timer sources + timerSource = reinterpret_cast(g_source_new(&timerSourceFuncs, + sizeof(GTimerSource))); + (void) new (&timerSource->timerList) QTimerInfoList(); + timerSource->processEventsFlags = QEventLoop::AllEvents; ++ timerSource->runWithIdlePriority = false; + g_source_set_can_recurse(&timerSource->source, true); +- g_source_set_priority(&timerSource->source, G_PRIORITY_DEFAULT_IDLE); + g_source_attach(&timerSource->source, mainContext); ++ ++ idleTimerSource = reinterpret_cast(g_source_new(&idleTimerSourceFuncs, ++ sizeof(GIdleTimerSource))); ++ idleTimerSource->timerSource = timerSource; ++ g_source_set_can_recurse(&idleTimerSource->source, true); ++ g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE); ++ g_source_attach(&idleTimerSource->source, mainContext); + } + + QEventDispatcherGlib::QEventDispatcherGlib(QObject *parent) +@@ -272,12 +346,9 @@ QEventDispatcherGlib::QEventDispatcherGlib(QObject *parent) + { + } + +-QEventDispatcherGlib::QEventDispatcherGlib(GMainContext *mainContext, +- QObject *parent) +- : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate(mainContext)), +- parent) +-{ +-} ++QEventDispatcherGlib::QEventDispatcherGlib(GMainContext *mainContext, QObject *parent) ++ : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate(mainContext)), parent) ++{ } + + QEventDispatcherGlib::~QEventDispatcherGlib() + { +@@ -289,6 +360,9 @@ QEventDispatcherGlib::~QEventDispatcherGlib() + g_source_destroy(&d->timerSource->source); + g_source_unref(&d->timerSource->source); + d->timerSource = 0; ++ g_source_destroy(&d->idleTimerSource->source); ++ g_source_unref(&d->idleTimerSource->source); ++ d->idleTimerSource = 0; + + // destroy socket notifier source + for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) { +@@ -324,11 +398,16 @@ bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) + // tell postEventSourcePrepare() and timerSource about any new flags + QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags; + d->timerSource->processEventsFlags = flags; +- ++ ++ if (!(flags & QEventLoop::EventLoopExec)) { ++ // force timers to be sent at normal priority ++ d->timerSource->runWithIdlePriority = false; ++ } ++ + bool result = g_main_context_iteration(d->mainContext, canWait); + while (!result && canWait) + result = g_main_context_iteration(d->mainContext, canWait); +- ++ + d->timerSource->processEventsFlags = savedFlags; + + if (canWait) +diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h +index eb7fb75..4103aa3 100644 +--- a/src/corelib/kernel/qeventdispatcher_glib_p.h ++++ b/src/corelib/kernel/qeventdispatcher_glib_p.h +@@ -98,6 +98,7 @@ protected: + struct GPostEventSource; + struct GSocketNotifierSource; + struct GTimerSource; ++struct GIdleTimerSource; + + class Q_CORE_EXPORT QEventDispatcherGlibPrivate : public QAbstractEventDispatcherPrivate + { +@@ -108,6 +109,7 @@ public: + GPostEventSource *postEventSource; + GSocketNotifierSource *socketNotifierSource; + GTimerSource *timerSource; ++ GIdleTimerSource *idleTimerSource; + }; + + QT_END_NAMESPACE +diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp +index 897bb49..903b0eb 100644 +--- a/src/corelib/kernel/qeventdispatcher_unix.cpp ++++ b/src/corelib/kernel/qeventdispatcher_unix.cpp +@@ -423,10 +423,10 @@ bool QTimerInfoList::timerWait(timeval &tm) + // Find first waiting timer not already active + QTimerInfo *t = 0; + for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) { +- if (!(*it)->inTimerEvent) { +- t = *it; +- break; +- } ++ if (!(*it)->inTimerEvent) { ++ t = *it; ++ break; ++ } + } + + if (!t) diff --git a/qt.spec b/qt.spec index a0070df..d728f11 100644 --- a/qt.spec +++ b/qt.spec @@ -4,13 +4,13 @@ # -no-pch disables precompiled headers, make ccache-friendly %define no_pch -no-pch -%define _default_patch_fuzz 2 +%define _default_patch_fuzz 2 Summary: Qt toolkit Name: qt Epoch: 1 Version: 4.5.3 -Release: 7%{?dist} +Release: 8%{?dist} # See LGPL_EXCEPTIONS.txt, LICENSE.GPL3, respectively, for exception details License: LGPLv2 with exceptions or GPLv3 with exceptions @@ -57,7 +57,10 @@ Patch53: qt-x11-opensource-src-4.5.0-fix-qatomic-inline-asm.patch # fix invalid assumptions about mysql_config --libs # http://bugzilla.redhat.com/440673 Patch54: qt-x11-opensource-src-4.5.1-mysql_config.patch +# glib-event-loop regression Patch55: qt-x11-opensource-src-4.5.3-glib-event-loop.patch +# or fix from http://bugs.kde.org/210171 +Patch155: http://www.davidfaure.fr/2009/qeventdispatcher_glib_fix.diff # security patches @@ -392,7 +395,8 @@ Qt libraries used for drawing widgets and OpenGL items. %patch52 -p1 -b .sparc64 %patch53 -p1 -b .qatomic-inline-asm %patch54 -p1 -b .mysql_config -%patch55 -p1 -b .glib-event-loop +#patch55 -p1 -b .glib-event-loop +%patch155 -p1 -b .qeventdispatcher_glib_fix # security fixes @@ -989,6 +993,9 @@ fi %changelog +* Fri Oct 30 2009 Rex Dieter - 4.5.3-8 +- use upstream qeventdispatcher_glib_fix.diff (kde#210171) + * Thu Oct 29 2009 Than Ngo - 4.5.3-7 - fix glib-even-loop issue, regression which causes Password dialogs get stuck