winrt: Explicitly set main thread in QCoreApplication's constructor
For winrt we cannot rely on the fact, that QThread::current will be called from the correct thread for the first time. The application's main entry point creates a suspended thread and starts it right afterwards. At that moment, other functionality (QLoggingRegistry for example) might have called QThread::current, which set the wrong thread as the main thread. In order to avoid this situation, the main thread is explicitly set in QCoreApplication's constructor. Task-number: QTBUG-66418 Change-Id: I8b6347357a80eb395ae758bd3d420adef0826751 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
05b8ba5155
commit
29208fa07c
@ -482,6 +482,10 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
|
||||
qFatal("FATAL: The application binary appears to be running setuid, this is a security hole.");
|
||||
# endif // Q_OS_UNIX
|
||||
|
||||
#ifdef Q_OS_WINRT
|
||||
QThreadData::setMainThread();
|
||||
#endif
|
||||
|
||||
QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
|
||||
if (cur != theMainThread)
|
||||
qWarning("WARNING: QApplication was not created in the main() thread.");
|
||||
|
@ -243,6 +243,9 @@ public:
|
||||
~QThreadData();
|
||||
|
||||
static Q_AUTOTEST_EXPORT QThreadData *current(bool createIfNecessary = true);
|
||||
#ifdef Q_OS_WINRT
|
||||
static void setMainThread();
|
||||
#endif
|
||||
static void clearCurrentThreadData();
|
||||
static QThreadData *get2(QThread *thread)
|
||||
{ Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; }
|
||||
|
@ -140,11 +140,15 @@ QThreadData *QThreadData::current(bool createIfNecessary)
|
||||
threadData->isAdopted = true;
|
||||
threadData->threadId.store(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
|
||||
|
||||
#ifndef Q_OS_WINRT
|
||||
if (!QCoreApplicationPrivate::theMainThread) {
|
||||
QCoreApplicationPrivate::theMainThread = threadData->thread.load();
|
||||
// TODO: is there a way to reflect the branch's behavior using
|
||||
// WinRT API?
|
||||
} else {
|
||||
#else
|
||||
// for winrt the main thread is set explicitly in QCoreApplication's constructor as the
|
||||
// native main thread (Xaml thread) is not Qt's main thread.
|
||||
{
|
||||
#endif
|
||||
HANDLE realHandle = INVALID_HANDLE_VALUE;
|
||||
DuplicateHandle(GetCurrentProcess(),
|
||||
GetCurrentThread(),
|
||||
@ -159,6 +163,33 @@ QThreadData *QThreadData::current(bool createIfNecessary)
|
||||
return threadData;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WINRT
|
||||
void QThreadData::setMainThread()
|
||||
{
|
||||
Q_ASSERT(!QCoreApplicationPrivate::theMainThread);
|
||||
qt_create_tls();
|
||||
QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
|
||||
if (!threadData) {
|
||||
threadData = new QThreadData;
|
||||
// This needs to be called prior to new AdoptedThread() to
|
||||
// avoid recursion.
|
||||
TlsSetValue(qt_current_thread_data_tls_index, threadData);
|
||||
QT_TRY {
|
||||
threadData->thread = new QAdoptedThread(threadData);
|
||||
} QT_CATCH(...) {
|
||||
TlsSetValue(qt_current_thread_data_tls_index, 0);
|
||||
threadData->deref();
|
||||
threadData = 0;
|
||||
QT_RETHROW;
|
||||
}
|
||||
threadData->deref();
|
||||
threadData->isAdopted = true;
|
||||
threadData->threadId.store(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
|
||||
}
|
||||
QCoreApplicationPrivate::theMainThread = threadData->thread.load();
|
||||
}
|
||||
#endif
|
||||
|
||||
void QAdoptedThread::init()
|
||||
{
|
||||
d_func()->handle = GetCurrentThread();
|
||||
|
Loading…
Reference in New Issue
Block a user