- use upstream qeventdispatcher_glib_fix.diff (kde#210171)
This commit is contained in:
parent
f47f9459f4
commit
c3defef042
282
qeventdispatcher_glib_fix.diff
Normal file
282
qeventdispatcher_glib_fix.diff
Normal file
@ -0,0 +1,282 @@
|
||||
commit 063bded33b417cdf92fd51366fc7fdb06dea00ba
|
||||
Author: Bradley T. Hughes <bradley.hughes@nokia.com>
|
||||
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<GTimerSource *>(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<GTimerSource *>(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<GTimerSource *>(source);
|
||||
+ if (src->runWithIdlePriority) {
|
||||
+ if (timeout)
|
||||
+ *timeout = -1;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return timerSourcePrepareHelper(src, timeout);
|
||||
+}
|
||||
+
|
||||
+static gboolean timerSourceCheck(GSource *source)
|
||||
+{
|
||||
+ GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
|
||||
+ if (src->runWithIdlePriority)
|
||||
+ return false;
|
||||
+ return timerSourceCheckHelper(src);
|
||||
+}
|
||||
+
|
||||
static gboolean timerSourceDispatch(GSource *source, GSourceFunc, gpointer)
|
||||
{
|
||||
- (void) reinterpret_cast<GTimerSource *>(source)->timerList.activateTimers();
|
||||
+ GTimerSource *timerSource = reinterpret_cast<GTimerSource *>(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<GIdleTimerSource *>(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<GIdleTimerSource *>(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<GIdleTimerSource *>(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<GPostEventSource *>(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<GTimerSource *>(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<GIdleTimerSource *>(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)
|
13
qt.spec
13
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 <rdieter@fedoraproject.org> - 4.5.3-8
|
||||
- use upstream qeventdispatcher_glib_fix.diff (kde#210171)
|
||||
|
||||
* Thu Oct 29 2009 Than Ngo <than@redhat.com> - 4.5.3-7
|
||||
- fix glib-even-loop issue, regression which causes
|
||||
Password dialogs get stuck
|
||||
|
Loading…
Reference in New Issue
Block a user