QThreadStorage: ensure global static exists when finish() is called
For the thread that calls ::exit() (usually, the main thread). Otherwise, depending on construction order, it is possible for the QThreadStorage's destructor list to have been destroyed by the time destroy_current_thread_data() → QThreadData::finish() calls our finish(). Fixes: QTBUG-135044 Pick-to: 6.9 6.8 Change-Id: Ic5a10367ff31e7faa039fffdc2067eba9642fbf9 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
7dc2532bed
commit
81a7a4c2d9
@ -748,7 +748,7 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_thread
|
||||
thread/qreadwritelock.cpp thread/qreadwritelock_p.h
|
||||
thread/qsemaphore.cpp thread/qsemaphore.h
|
||||
thread/qthreadpool.cpp thread/qthreadpool.h thread/qthreadpool_p.h
|
||||
thread/qthreadstorage.cpp
|
||||
thread/qthreadstorage.cpp thread/qthreadstorage_p.h
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND UNIX
|
||||
|
@ -17,18 +17,19 @@
|
||||
//
|
||||
//
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include "QtCore/qthread.h"
|
||||
#include "QtCore/qmutex.h"
|
||||
#include "QtCore/qstack.h"
|
||||
#if QT_CONFIG(thread)
|
||||
#include "QtCore/qwaitcondition.h"
|
||||
#endif
|
||||
#include "QtCore/qmap.h"
|
||||
|
||||
#include "QtCore/qcoreapplication.h"
|
||||
#include "private/qobject_p.h"
|
||||
#include "QtCore/qmap.h"
|
||||
#include "QtCore/qmutex.h"
|
||||
#include "QtCore/qstack.h"
|
||||
|
||||
#if QT_CONFIG(thread)
|
||||
#include "private/qthreadstorage_p.h"
|
||||
#include "QtCore/qwaitcondition.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -223,6 +223,7 @@ struct QThreadDataDestroyer
|
||||
}
|
||||
|
||||
struct EarlyMainThread {
|
||||
EarlyMainThread() { QThreadStoragePrivate::init(); }
|
||||
~EarlyMainThread()
|
||||
{
|
||||
// running function-local destructors upon ::exit()
|
||||
|
@ -82,6 +82,7 @@ static void set_thread_data(QThreadData *data) noexcept
|
||||
{
|
||||
if (data) {
|
||||
struct Cleanup {
|
||||
Cleanup() { QThreadStoragePrivate::init(); }
|
||||
~Cleanup() { destroy_current_thread_data(currentThreadData); }
|
||||
};
|
||||
static thread_local Cleanup currentThreadCleanup;
|
||||
|
@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qthreadstorage.h"
|
||||
#include "qthreadstorage_p.h"
|
||||
|
||||
#include "private/qcoreapplication_p.h"
|
||||
#include "qthread.h"
|
||||
@ -133,6 +134,13 @@ void **QThreadStorageData::set(void *p)
|
||||
return &value;
|
||||
}
|
||||
|
||||
void QThreadStoragePrivate::init()
|
||||
{
|
||||
// Make sure the Q_GLOBAL_STATIC is initialized, ensuring consistent
|
||||
// destruction order.
|
||||
destructors();
|
||||
}
|
||||
|
||||
void QThreadStorageData::finish(void **p)
|
||||
{
|
||||
QList<void *> *tls = reinterpret_cast<QList<void *> *>(p);
|
||||
|
29
src/corelib/thread/qthreadstorage_p.h
Normal file
29
src/corelib/thread/qthreadstorage_p.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2025 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QTHREADSTORAGE_P_H
|
||||
#define QTHREADSTORAGE_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <qlist.h>
|
||||
#include <private/qglobal_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QThreadStoragePrivate {
|
||||
void init();
|
||||
} // namespace QThreadStoragePrivate
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QTHREADSTORAGE_P_H
|
Loading…
x
Reference in New Issue
Block a user