summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qthread.cpp
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2025-08-04 16:28:53 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2025-08-27 13:19:24 +0200
commit2d92ea02501c058f55a8562f55804ccb105bf4bf (patch)
treeca238cb533cd97f65a21aba90470a868e605690d /src/corelib/thread/qthread.cpp
parentf5d936642b18c5d06942171530a164499e4e9113 (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.cpp15
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);
}