summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-10-12 09:13:02 -0700
committerThiago Macieira <thiago.macieira@intel.com>2024-05-07 14:22:27 -0700
commit1ed0dd88a32cd2c5ae100b48e14ff55bcbb652e6 (patch)
tree5173b160b09f9980ce146f1645cb85dc702a3033 /src/corelib/thread
parent3fc5ee5c2e4ed919b2939ca54a1958b8463eb404 (diff)
QThread/Unix: make QThreadPrivate::finish() be called much later
We need it to run after all the thread-local destructors have run, to ensure that some user code hasn't run after QThreadPrivate::finish() has finished. We achieve that by making it get called from a thread-local destructor itself, in the form of a qScopeGuard. This ought to have been done since C++11 thread_local with non-trivial destructors became available. However, it only started showing up after commit 4a93285b166ceceaea2e10c8fc6a254d2f7093b9 began using thread_local inside Qt itself. The visible symptom was that QThreadPrivate::finish() had already destroyed the thread's event dispatcher, but some user code ran later and expected it to still exist (or, worse, recreated it, via QEventLoop → QThreadData::ensureEventDispatcher). Fixes: QTBUG-117996 Pick-to: 6.7 Change-Id: I8f3ce163ccc5408cac39fffd178d682e5bfa6955 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/corelib/thread')
-rw-r--r--src/corelib/thread/qthread_unix.cpp14
1 files changed, 7 insertions, 7 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 617a5ebf28..556f05018f 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -282,8 +282,12 @@ void *QThreadPrivate::start(void *arg)
#ifdef PTHREAD_CANCEL_DISABLE
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr);
#endif
- pthread_cleanup_push(QThreadPrivate::finish, arg);
-
+#if !defined(Q_OS_QNX)
+ // On QNX, calling finish() from a thread_local destructor causes the C
+ // library to hang.
+ static thread_local
+#endif
+ auto cleanup = qScopeGuard([=] { finish(arg); });
terminate_on_exception([&] {
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadData *data = QThreadData::get2(thr);
@@ -328,11 +332,7 @@ void *QThreadPrivate::start(void *arg)
thr->run();
});
- // This pop runs finish() below. It's outside the try/catch (and has its
- // own try/catch) to prevent finish() to be run in case an exception is
- // thrown.
- pthread_cleanup_pop(1);
-
+ // The qScopeGuard above call runs finish() below.
return nullptr;
}