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:
parent
4ec169a60f
commit
39c2fdd907
@ -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)
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user