Don't access QObject::objectName during QThread start

This is a data race, as the thread accesses QObject::objectName on the
QThread instance while the thread owning the QThread might modify the
objectName.

Instead, make a copy in the QThreadPrivate that can be accessed safely.

Task-number: QTBUG-96718
Pick-to: 6.3 6.2 5.15
Change-Id: I10701551d498993ca5055daf161636bfb648840c
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
bb10
Volker Hilsheimer 2022-01-10 18:10:48 +01:00
parent e9fd1c6aab
commit 4a4240f1bd
3 changed files with 16 additions and 6 deletions

View File

@ -201,6 +201,13 @@ public:
QCoreApplication::instance()->postEvent(q_ptr, new QEvent(QEvent::Quit));
}
}
#ifndef Q_OS_INTEGRITY
private:
// Used in QThread(Private)::start to avoid racy access to QObject::objectName,
// unset afterwards. On INTEGRITY we set the thread name before starting it.
QString objectName;
#endif
};
#else // QT_CONFIG(thread)

View File

@ -343,10 +343,10 @@ void *QThreadPrivate::start(void *arg)
// Sets the name of the current thread. We can only do this
// when the thread is starting, as we don't have a cross
// platform way of setting the name of an arbitrary thread.
if (Q_LIKELY(thr->objectName().isEmpty()))
if (Q_LIKELY(thr->d_func()->objectName.isEmpty()))
setCurrentThreadName(thr->metaObject()->className());
else
setCurrentThreadName(thr->objectName().toLocal8Bit());
setCurrentThreadName(std::exchange(thr->d_func()->objectName, {}).toLocal8Bit());
}
#endif
@ -734,7 +734,10 @@ void QThread::start(Priority priority)
pthread_attr_setthreadname(&attr, metaObject()->className());
else
pthread_attr_setthreadname(&attr, objectName().toLocal8Bit());
#else
d->objectName = objectName();
#endif
pthread_t threadId;
int code = pthread_create(&threadId, &attr, QThreadPrivate::start, this);
if (code == EPERM) {

View File

@ -316,10 +316,9 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC)
// sets the name of the current thread.
QByteArray objectName = thr->objectName().toLocal8Bit();
qt_set_thread_name(HANDLE(-1),
objectName.isEmpty() ?
thr->metaObject()->className() : objectName.constData());
qt_set_thread_name(HANDLE(-1), thr->d_func()->objectName.isEmpty()
? thr->metaObject()->className()
: std::exchange(thr->d_func()->objectName, {}).toLocal8Bit().constData());
#endif
emit thr->started(QThread::QPrivateSignal());
@ -421,6 +420,7 @@ void QThread::start(Priority priority)
if (d->running)
return;
d->objectName = objectName();
d->running = true;
d->finished = false;
d->exited = false;