qtbase/config.tests/cxa_thread_atexit/main.c

24 lines
954 B
C
Raw Permalink Normal View History

QThread/Unix: refactor to split QThreadPrivate::finish() in two phases Commit 1ed0dd88a32cd2c5ae100b48e14ff55bcbb652e6 moved the finish() functionality from immediately after run() returns to the time of thread-local destruction, to make sure that user destructors didn't run after our cleaning up. But as a side effect, it made other user code run too late, after some thread-local statics had been destroyed. This is a common practice, which causes the destructor for worker to run too late: worker->moveToThread(thread); ... QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater); QObject::connect(thread, &QThread::finished, worker, &QObject::deleteLater); This commit splits the cleanup in two phases: QThreadPrivate::finish(), which runs immediately after run() and will call back out to user code (finished() signal and delivery of deleteLater()), and cleanup() that cleans up the QThread{Private,Data} state and destroys the event dispatcher. That destruction is the only call out to user code. I've removed the complex mix of pre-C++11 pthread_setspecific() content and C++11 thread_local variables in favor of using one or the other, not both. We prefer the thread-local for future-proofing and simplicity, on platforms where we can verify this C++11 feature works, and because it allows us to clean up QThreadData and the event dispatcher as late as possible. (There's some code that runs even later, such as pthread TLS destructors, used by Glib's GMainLoop) Unfortunately, we can't use it everywhere. The commit above had already noticed QNX has a problem and recent bug reports have shown other platforms (Solaris, MUSL libc) that, 13 years after the ratification of the standard, still have broken support, so we use pthread for them and we call cleanup() from within finish() (that is, no late cleaning-up, retaining the status quo from Qt 4 and 5). See QTBUG-129846 for an analysis. Drive-by moving the resetting of thread priority to after finished() is emitted. [ChangeLog][QtCore][QThread] Restored the Qt 6.7 timing of when the finished() signal is emitted relative to the destruction of thread_local variables. Qt 6.8.0 contained a change that moved this signal to a later time on most Unix systems, which has caused problems with the order in which those variables were accessed. The destruction of the event dispatcher is kept at this late stage, wherever possible. Fixes: QTBUG-129927 Fixes: QTBUG-129846 Fixes: QTBUG-130341 Task-number: QTBUG-117996 Pick-to: 6.8 Change-Id: Ie5e40dd18faa05d8f777fffdf7dc30fc4fe0c7e9 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-10-15 16:17:39 +00:00
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
#include <stddef.h>
#if defined(__vxworks) || defined(__VXWORKS__)
/*
* In VxWorks pthread implementation, when thread is finishing it calls pthread_exit(), which:
* - calls pthread cleanup procedure
* - clears pthread data (setting current thread to null)
* - calls `taskExit` VxWorks system procedure
* `taskExit` procedure calls thread_local object destructors, which if call directly or indirectly
* `pthread_self()`, terminate with error, due to not being able to obtain pthread entity.
* Thus, we need to treat VxWorks pthread implementation as `broken` in terms of thread_local variables.
*/
# error "VxWorks threadlocal destructors are called after pthread data is destroyed, causing crash."
#endif
QThread/Unix: refactor to split QThreadPrivate::finish() in two phases Commit 1ed0dd88a32cd2c5ae100b48e14ff55bcbb652e6 moved the finish() functionality from immediately after run() returns to the time of thread-local destruction, to make sure that user destructors didn't run after our cleaning up. But as a side effect, it made other user code run too late, after some thread-local statics had been destroyed. This is a common practice, which causes the destructor for worker to run too late: worker->moveToThread(thread); ... QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater); QObject::connect(thread, &QThread::finished, worker, &QObject::deleteLater); This commit splits the cleanup in two phases: QThreadPrivate::finish(), which runs immediately after run() and will call back out to user code (finished() signal and delivery of deleteLater()), and cleanup() that cleans up the QThread{Private,Data} state and destroys the event dispatcher. That destruction is the only call out to user code. I've removed the complex mix of pre-C++11 pthread_setspecific() content and C++11 thread_local variables in favor of using one or the other, not both. We prefer the thread-local for future-proofing and simplicity, on platforms where we can verify this C++11 feature works, and because it allows us to clean up QThreadData and the event dispatcher as late as possible. (There's some code that runs even later, such as pthread TLS destructors, used by Glib's GMainLoop) Unfortunately, we can't use it everywhere. The commit above had already noticed QNX has a problem and recent bug reports have shown other platforms (Solaris, MUSL libc) that, 13 years after the ratification of the standard, still have broken support, so we use pthread for them and we call cleanup() from within finish() (that is, no late cleaning-up, retaining the status quo from Qt 4 and 5). See QTBUG-129846 for an analysis. Drive-by moving the resetting of thread priority to after finished() is emitted. [ChangeLog][QtCore][QThread] Restored the Qt 6.7 timing of when the finished() signal is emitted relative to the destruction of thread_local variables. Qt 6.8.0 contained a change that moved this signal to a later time on most Unix systems, which has caused problems with the order in which those variables were accessed. The destruction of the event dispatcher is kept at this late stage, wherever possible. Fixes: QTBUG-129927 Fixes: QTBUG-129846 Fixes: QTBUG-130341 Task-number: QTBUG-117996 Pick-to: 6.8 Change-Id: Ie5e40dd18faa05d8f777fffdf7dc30fc4fe0c7e9 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-10-15 16:17:39 +00:00
typedef void (*dtor_func) (void *);
int TEST_FUNC(dtor_func func, void *obj, void *dso_symbol);
int main()
{
return TEST_FUNC(NULL, NULL, NULL);
}