summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOliver Wolff <oliver.wolff@qt.io>2018-09-10 12:19:09 +0200
committerOliver Wolff <oliver.wolff@qt.io>2018-10-08 05:34:28 +0000
commit29208fa07c1b9f656ea2535696828385b7832226 (patch)
treee784dcdd1896f836d81ebeb4f6eb67426923b9f9 /src
parent05b8ba51550127c85cd2db5cb819b695b56c57ce (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.cpp4
-rw-r--r--src/corelib/thread/qthread_p.h3
-rw-r--r--src/corelib/thread/qthread_win.cpp35
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();