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/qreadwritelock.cpp thread/qreadwritelock_p.h
|
||||||
thread/qsemaphore.cpp thread/qsemaphore.h
|
thread/qsemaphore.cpp thread/qsemaphore.h
|
||||||
thread/qthreadpool.cpp thread/qthreadpool.h thread/qthreadpool_p.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
|
qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND UNIX
|
||||||
|
@ -17,18 +17,19 @@
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "qplatformdefs.h"
|
|
||||||
#include "QtCore/qthread.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 "QtCore/qcoreapplication.h"
|
||||||
#include "private/qobject_p.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>
|
#include <atomic>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
@ -223,6 +223,7 @@ struct QThreadDataDestroyer
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct EarlyMainThread {
|
struct EarlyMainThread {
|
||||||
|
EarlyMainThread() { QThreadStoragePrivate::init(); }
|
||||||
~EarlyMainThread()
|
~EarlyMainThread()
|
||||||
{
|
{
|
||||||
// running function-local destructors upon ::exit()
|
// running function-local destructors upon ::exit()
|
||||||
|
@ -82,6 +82,7 @@ static void set_thread_data(QThreadData *data) noexcept
|
|||||||
{
|
{
|
||||||
if (data) {
|
if (data) {
|
||||||
struct Cleanup {
|
struct Cleanup {
|
||||||
|
Cleanup() { QThreadStoragePrivate::init(); }
|
||||||
~Cleanup() { destroy_current_thread_data(currentThreadData); }
|
~Cleanup() { destroy_current_thread_data(currentThreadData); }
|
||||||
};
|
};
|
||||||
static thread_local Cleanup currentThreadCleanup;
|
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
|
// 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.h"
|
||||||
|
#include "qthreadstorage_p.h"
|
||||||
|
|
||||||
#include "private/qcoreapplication_p.h"
|
#include "private/qcoreapplication_p.h"
|
||||||
#include "qthread.h"
|
#include "qthread.h"
|
||||||
@ -133,6 +134,13 @@ void **QThreadStorageData::set(void *p)
|
|||||||
return &value;
|
return &value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QThreadStoragePrivate::init()
|
||||||
|
{
|
||||||
|
// Make sure the Q_GLOBAL_STATIC is initialized, ensuring consistent
|
||||||
|
// destruction order.
|
||||||
|
destructors();
|
||||||
|
}
|
||||||
|
|
||||||
void QThreadStorageData::finish(void **p)
|
void QThreadStorageData::finish(void **p)
|
||||||
{
|
{
|
||||||
QList<void *> *tls = reinterpret_cast<QList<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