QThread/Unix: move the pthread_key to a file-scope static
So that the pthread_key is destroyed much later than now, at QtCore unload time instead of a bit earlier in exit(). That's important so it runs later than the Q_DESTRUCTOR_FUNCTION for QLibraryStore (qlibrary.cpp), which is what unloads plugins, whose unload-time destructors may be attempting to quit() & wait() for their worker threads. I had to keep the destruction of the exiting thread's adopted thread where it was: a function-local static's destructor. As noted in the comment added by 1da7558bfd7626bcc40a214a90ae5027f32f6c7f, we need QThreadData::cleanup() to run before the libraries start to unload because we need to delete the event dispatcher. Init priority 10 will place it after the QHash random seed and qsimd initialization, on ELF systems and on Windows. On other systems (incl. Apple ones), the order probably depends on the order of the files in the CMakeLists.txt. I thought that would mean the destructor for thread/ would run before plugin/ but that apparently is not the case. But that's fragile. Amends 1da7558bfd7626bcc40a214a90ae5027f32f6c7f, which amended other things... Fixes: QTBUG-132697 Task-number: QTBUG-102984 Task-number: QTBUG-132381 Pick-to: 6.8 Change-Id: Id7263d6ffe7a5949cd84e35d942ad0e02df1b455 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit 2f69a05bd0cd7ce63890f709ff3ed7a4f78acd70) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
ea6d467c05
commit
4f6c2fd9d7
@ -140,6 +140,12 @@ static void destroy_current_thread_data(void *p)
|
||||
QThreadData *data = static_cast<QThreadData *>(p);
|
||||
QThread *thread = data->thread.loadAcquire();
|
||||
|
||||
#ifdef Q_OS_APPLE
|
||||
// apparent runtime bug: the trivial has been cleared and we end up
|
||||
// recreating the QThreadData
|
||||
currentThreadData = data;
|
||||
#endif
|
||||
|
||||
if (data->isAdopted) {
|
||||
// If this is an adopted thread, then QThreadData owns the QThread and
|
||||
// this is very likely the last reference. These pointers cannot be
|
||||
@ -173,21 +179,32 @@ static QThreadData *get_thread_data()
|
||||
return currentThreadData;
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct PThreadTlsKey
|
||||
{
|
||||
pthread_key_t key;
|
||||
PThreadTlsKey() noexcept { pthread_key_create(&key, destroy_current_thread_data); }
|
||||
~PThreadTlsKey() { pthread_key_delete(key); }
|
||||
};
|
||||
}
|
||||
#if QT_SUPPORTS_INIT_PRIORITY
|
||||
Q_DECL_INIT_PRIORITY(10)
|
||||
#endif
|
||||
static PThreadTlsKey pthreadTlsKey; // intentional non-trivial init & destruction
|
||||
|
||||
static void set_thread_data(QThreadData *data) noexcept
|
||||
{
|
||||
if (data) {
|
||||
static pthread_key_t tls_key;
|
||||
struct TlsKey {
|
||||
TlsKey() noexcept { pthread_key_create(&tls_key, destroy_current_thread_data); }
|
||||
~TlsKey()
|
||||
{
|
||||
if (QThreadData *data = currentThreadData)
|
||||
// As noted above: one global static for the thread that called
|
||||
// ::exit() (which may not be a Qt thread) and the pthread_key_t for
|
||||
// all others.
|
||||
static struct Cleanup {
|
||||
~Cleanup() {
|
||||
if (QThreadData *data = get_thread_data())
|
||||
destroy_current_thread_data(data);
|
||||
pthread_key_delete(tls_key);
|
||||
}
|
||||
};
|
||||
static TlsKey currentThreadCleanup;
|
||||
pthread_setspecific(tls_key, data);
|
||||
} currentThreadCleanup;
|
||||
pthread_setspecific(pthreadTlsKey.key, data);
|
||||
}
|
||||
currentThreadData = data;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user