From f4609b202208fe592d24c7ae3b4a48ee83045497 Mon Sep 17 00:00:00 2001 From: David Faure Date: Mon, 18 Mar 2013 15:19:44 +0100 Subject: QThread: fix race when setting the eventDispatcher Use QAtomicPointer to make this thread-safe. Change-Id: If71f204699fcefabdb59bd26342d777d1cc9e2a7 Reviewed-by: Olivier Goffart --- src/corelib/thread/qthread.cpp | 4 ++-- src/corelib/thread/qthread_p.h | 4 +++- src/corelib/thread/qthread_unix.cpp | 14 +++++++------- src/corelib/thread/qthread_win.cpp | 11 ++++++----- 4 files changed, 18 insertions(+), 15 deletions(-) (limited to 'src/corelib/thread') diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index dd4d4e74ae..d230c8a145 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -752,7 +752,7 @@ QThread::QThread(QThreadPrivate &dd, QObject *parent) QAbstractEventDispatcher *QThread::eventDispatcher() const { Q_D(const QThread); - return d->data->eventDispatcher; + return d->data->eventDispatcher.load(); } /*! @@ -767,7 +767,7 @@ QAbstractEventDispatcher *QThread::eventDispatcher() const void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) { Q_D(QThread); - if (d->data->eventDispatcher != 0) { + if (d->data->hasEventDispatcher()) { qWarning("QThread::setEventDispatcher: An event dispatcher has already been created for this thread"); } else { eventDispatcher->moveToThread(this); diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 8e9eb1035a..7e963fdcd1 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -230,6 +230,8 @@ public: void ref(); void deref(); + inline bool hasEventDispatcher() const + { return eventDispatcher.load() != 0; } bool canWaitLocked() { @@ -241,7 +243,7 @@ public: Qt::HANDLE threadId; bool quitNow; int loopLevel; - QAbstractEventDispatcher *eventDispatcher; + QAtomicPointer eventDispatcher; QStack eventLoops; QPostEventList postEventList; bool canWait; diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 44ad8d3ac2..b7e94366fe 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -258,19 +258,19 @@ typedef void*(*QtThreadCallback)(void*); void QThreadPrivate::createEventDispatcher(QThreadData *data) { #if defined(Q_OS_BLACKBERRY) - data->eventDispatcher = new QEventDispatcherBlackberry; + data->eventDispatcher.storeRelease(new QEventDispatcherBlackberry); #else #if !defined(QT_NO_GLIB) if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") && qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB") && QEventDispatcherGlib::versionSupported()) - data->eventDispatcher = new QEventDispatcherGlib; + data->eventDispatcher.storeRelease(new QEventDispatcherGlib); else #endif - data->eventDispatcher = new QEventDispatcherUNIX; + data->eventDispatcher.storeRelease(new QEventDispatcherUNIX); #endif - data->eventDispatcher->startingUp(); + data->eventDispatcher.load()->startingUp(); } #ifndef QT_NO_THREAD @@ -314,8 +314,8 @@ void *QThreadPrivate::start(void *arg) data->quitNow = thr->d_func()->exited; } - if (data->eventDispatcher) // custom event dispatcher set? - data->eventDispatcher->startingUp(); + if (data->eventDispatcher.load()) // custom event dispatcher set? + data->eventDispatcher.load()->startingUp(); else createEventDispatcher(data); @@ -358,7 +358,7 @@ void QThreadPrivate::finish(void *arg) QThreadStorageData::finish((void **)data); locker.relock(); - QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher; + QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load(); if (eventDispatcher) { d->data->eventDispatcher = 0; locker.unlock(); diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 0cf903bb3a..ddf499f3bb 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -306,8 +306,9 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) void QThreadPrivate::createEventDispatcher(QThreadData *data) { - data->eventDispatcher = new QEventDispatcherWin32; - data->eventDispatcher->startingUp(); + QEventDispatcherWin32 *theEventDispatcher = new QEventDispatcherWin32; + data->eventDispatcher.storeRelease(theEventDispatcher); + theEventDispatcher->startingUp(); } #ifndef QT_NO_THREAD @@ -328,8 +329,8 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi data->quitNow = thr->d_func()->exited; } - if (data->eventDispatcher) // custom event dispatcher set? - data->eventDispatcher->startingUp(); + if (data->eventDispatcher.load()) // custom event dispatcher set? + data->eventDispatcher.load()->startingUp(); else createEventDispatcher(data); @@ -364,7 +365,7 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) QThreadStorageData::finish(tls_data); locker.relock(); - QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher; + QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load(); if (eventDispatcher) { d->data->eventDispatcher = 0; locker.unlock(); -- cgit v1.2.3