diff options
| author | Fabian Kosmale <fabian.kosmale@qt.io> | 2025-08-04 16:28:53 +0200 |
|---|---|---|
| committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2025-08-27 13:19:24 +0200 |
| commit | 2d92ea02501c058f55a8562f55804ccb105bf4bf (patch) | |
| tree | ca238cb533cd97f65a21aba90470a868e605690d /src/corelib/thread/qthread.cpp | |
| parent | f5d936642b18c5d06942171530a164499e4e9113 (diff) | |
QProperty: Avoid referencing stale QBindingStatus
Because we cache the QBindingStatus in QObjects, and the QObjects might
outlive the native thread, we can't bind the lifetime of the
QBindingStatus solely to the native thread.
Instead, keep it alive while the QThreadData associated with the QObject
still exists.
This is done by moving the BindingStatusOrList member for QThreadPrivate
to QThreadData, and by letting QThreadData own the binding status.
Pick-to: 6.10 6.9 6.8 6.5
Fixes: QTBUG-126134
Change-Id: I747ec1778f6b6f376c38d1c678dc5b2f62fcb7ef
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/corelib/thread/qthread.cpp')
| -rw-r--r-- | src/corelib/thread/qthread.cpp | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 3160ee27c37..553b38fec8f 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -118,7 +118,7 @@ QAdoptedThread::QAdoptedThread(QThreadData *data) #if QT_CONFIG(thread) d_func()->threadState = QThreadPrivate::Running; init(); - d_func()->m_statusOrPendingObjects.setStatusAndClearList( + d_func()->data->m_statusOrPendingObjects.setStatusAndClearList( QtPrivate::getBindingStatus({})); #endif // fprintf(stderr, "new QAdoptedThread = %p\n", this); @@ -173,7 +173,7 @@ QThreadPrivate::~QThreadPrivate() // access to m_statusOrPendingObjects cannot race with anything // unless there is already a potential use-after-free bug, as the // thread is in the process of being destroyed - delete m_statusOrPendingObjects.list(); + delete data->m_statusOrPendingObjects.list(); data->clearEvents(); data->deref(); } @@ -625,7 +625,6 @@ QThread::QualityOfService QThread::serviceLevel() const */ void QtPrivate::BindingStatusOrList::setStatusAndClearList(QBindingStatus *status) noexcept { - if (auto pendingObjects = list()) { for (auto obj: *pendingObjects) QObjectPrivate::get(obj)->reinitBindingStorageAfterThreadMove(); @@ -654,7 +653,7 @@ int QThread::exec() const auto status = QtPrivate::getBindingStatus(QtPrivate::QBindingStatusAccessToken{}); QMutexLocker locker(&d->mutex); - d->m_statusOrPendingObjects.setStatusAndClearList(status); + d->data->m_statusOrPendingObjects.setStatusAndClearList(status); d->data->quitNow = false; if (d->exited) { d->exited = false; @@ -708,18 +707,18 @@ void QtPrivate::BindingStatusOrList::removeObject(QObject *object) QBindingStatus *QThreadPrivate::addObjectWithPendingBindingStatusChange(QObject *obj) { - if (auto status = m_statusOrPendingObjects.bindingStatus()) + if (auto status = data->m_statusOrPendingObjects.bindingStatus()) return status; QMutexLocker lock(&mutex); - return m_statusOrPendingObjects.addObjectUnlessAlreadyStatus(obj); + return data->m_statusOrPendingObjects.addObjectUnlessAlreadyStatus(obj); } void QThreadPrivate::removeObjectWithPendingBindingStatusChange(QObject *obj) { - if (m_statusOrPendingObjects.bindingStatus()) + if (data->m_statusOrPendingObjects.bindingStatus()) return; QMutexLocker lock(&mutex); - m_statusOrPendingObjects.removeObject(obj); + data->m_statusOrPendingObjects.removeObject(obj); } |
