diff options
author | Oliver Wolff <oliver.wolff@qt.io> | 2018-09-10 12:19:09 +0200 |
---|---|---|
committer | Oliver Wolff <oliver.wolff@qt.io> | 2018-10-08 05:34:28 +0000 |
commit | 29208fa07c1b9f656ea2535696828385b7832226 (patch) | |
tree | e784dcdd1896f836d81ebeb4f6eb67426923b9f9 /src | |
parent | 05b8ba51550127c85cd2db5cb819b695b56c57ce (diff) |
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 4 | ||||
-rw-r--r-- | src/corelib/thread/qthread_p.h | 3 | ||||
-rw-r--r-- | src/corelib/thread/qthread_win.cpp | 35 |
3 files changed, 40 insertions, 2 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 1350a7aa94..463e30e1c3 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -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."); diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 64e3f33191..7d9442ab79 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -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; } diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index eebaf90d9b..e04d27d7b6 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -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(); |