From ba6c1d2785ca6d8a8b162abcd9d978ab0c52ea2d Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Thu, 24 Feb 2022 09:03:26 +0100 Subject: QProperty: fix threading issues QObject's cache the binding status pointer to avoid TLS lookups. However, when an object is moved to a different thread, we need to update the cached pointer (as the original thread might stop and thus no longer exist, and to correctly allow setting up bindings in the object's thread). Fix this by also storing the binding status in QThreadPrivate and updating the object's binding status when moved. This does only work when the thread is already running, though. If it is not running, we instead treat the QThreadPrivate's status pointer as a pointer to a vector of pending objects. Once the QThread has been started, we check if there are pending objects, and update them at this point. Pick-to: 6.2 6.3 Fixes: QTBUG-101177 Change-Id: I0490bbbdc1a17cb5f85044ad6eb2e1a8c759d4b7 Reviewed-by: Qt CI Bot Reviewed-by: Ulf Hermann --- src/corelib/thread/qthread.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/corelib/thread/qthread.cpp') diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 4cfcab2258..994d77926c 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -43,6 +43,7 @@ #include "qmutex.h" #include "qreadwritelock.h" #include "qabstracteventdispatcher.h" +#include "qbindingstorage.h" #include @@ -195,6 +196,7 @@ QThreadPrivate::QThreadPrivate(QThreadData *d) QThreadPrivate::~QThreadPrivate() { + delete pendingObjectsWithBindingStatusChange(); data->deref(); } @@ -552,6 +554,13 @@ uint QThread::stackSize() const int QThread::exec() { Q_D(QThread); + const auto status = QtPrivate::getBindingStatus(QtPrivate::QBindingStatusAccessToken{}); + if (auto pendingObjects = d->pendingObjectsWithBindingStatusChange()) { + for (auto obj: *pendingObjects) + QObjectPrivate::get(obj)->reinitBindingStorageAfterThreadMove(); + delete pendingObjects; + } + d->m_statusOrPendingObjects.storeRelease(quintptr(status)); QMutexLocker locker(&d->mutex); d->data->quitNow = false; if (d->exited) { @@ -953,6 +962,7 @@ QThreadPrivate::QThreadPrivate(QThreadData *d) : data(d ? d : new QThreadData) QThreadPrivate::~QThreadPrivate() { + delete pendingObjectsWithBindingStatusChange(); data->thread.storeRelease(nullptr); // prevent QThreadData from deleting the QThreadPrivate (again). delete data; } -- cgit v1.2.3