QWindowSystemInterface: fix mem leak and race

There was a race where QGuiApplicationPrivate::processMouseEvent accessed
QWindowSystemInterfacePrivate::windowSystemEventQueue without holding
QWindowSystemInterfacePrivate::queueMutex.

There was a memory leak where QWindowSystemInterfacePrivate::windowSystemEventQueue
would not delete events contained in it when it was destroyed.

Fix both of these by properly encapsulating the QList/QMutex pair
in a small class, WindowSystemEventList, that allows only properly protected access
to the internal QList and calls qDeleteAll() in its dtor.

Change-Id: Ifaa9968c9272096df2f7109a7a6cf1c8e5fa736c
Reviewed-by: David Faure <faure@kde.org>
Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
This commit is contained in:
Marc Mutz 2012-08-06 16:07:38 +02:00 committed by Qt by Nokia
parent 4ec169a60f
commit 39c2fdd907
2 changed files with 26 additions and 18 deletions

View File

@ -58,8 +58,7 @@ QElapsedTimer QWindowSystemInterfacePrivate::eventTime;
// Callback functions for plugins:
//
QList<QWindowSystemInterfacePrivate::WindowSystemEvent *> QWindowSystemInterfacePrivate::windowSystemEventQueue;
QMutex QWindowSystemInterfacePrivate::queueMutex;
QWindowSystemInterfacePrivate::WindowSystemEventList QWindowSystemInterfacePrivate::windowSystemEventQueue;
extern QPointer<QWindow> qt_last_mouse_receiver;
@ -330,29 +329,17 @@ QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *exposed, const
int QWindowSystemInterfacePrivate::windowSystemEventsQueued()
{
queueMutex.lock();
int ret = windowSystemEventQueue.count();
queueMutex.unlock();
return ret;
return windowSystemEventQueue.count();
}
QWindowSystemInterfacePrivate::WindowSystemEvent * QWindowSystemInterfacePrivate::getWindowSystemEvent()
{
queueMutex.lock();
QWindowSystemInterfacePrivate::WindowSystemEvent *ret;
if (windowSystemEventQueue.isEmpty())
ret = 0;
else
ret = windowSystemEventQueue.takeFirst();
queueMutex.unlock();
return ret;
return windowSystemEventQueue.takeFirstOrReturnNull();
}
void QWindowSystemInterfacePrivate::queueWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
{
queueMutex.lock();
windowSystemEventQueue.append(ev);
queueMutex.unlock();
QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher();
if (dispatcher)

View File

@ -45,6 +45,8 @@
#include <QElapsedTimer>
#include <QPointer>
#include <QMutex>
#include <QList>
QT_BEGIN_HEADER
@ -323,8 +325,27 @@ public:
qint64 uid;
};
static QList<WindowSystemEvent *> windowSystemEventQueue;
static QMutex queueMutex;
class WindowSystemEventList {
QList<WindowSystemEvent *> impl;
mutable QMutex mutex;
public:
WindowSystemEventList() : impl(), mutex() {}
~WindowSystemEventList()
{ const QMutexLocker locker(&mutex); qDeleteAll(impl); impl.clear(); }
void prepend(WindowSystemEvent *e)
{ const QMutexLocker locker(&mutex); impl.prepend(e); }
WindowSystemEvent *takeFirstOrReturnNull()
{ const QMutexLocker locker(&mutex); return impl.empty() ? 0 : impl.takeFirst(); }
void append(WindowSystemEvent *e)
{ const QMutexLocker locker(&mutex); impl.append(e); }
int count() const
{ const QMutexLocker locker(&mutex); return impl.count(); }
private:
Q_DISABLE_COPY(WindowSystemEventList);
};
static WindowSystemEventList windowSystemEventQueue;
static int windowSystemEventsQueued();
static WindowSystemEvent * getWindowSystemEvent();