tst_Q*Application: avoid race conditions during exitFromThread

Amends commit bfbd1a281dd00c47df315c06e895bf5d53cd8764. I've noticed
this on my Mac, because the main thread crashed at the same time as the
exitFromThread() thread was exiting and was running ~QLibraryStore:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x106)
  * frame #0: 0x00007ff8020533be libobjc.A.dylib`getMethodNoSuper_nolock(objc_class*, objc_selector*) + 47
...
    frame #19: 0x0000000103839694 QtCore`QCoreApplication::exec() at qcoreapplication.cpp:1454:32
    frame #20: 0x0000000101fc94ea QtGui`QGuiApplication::exec() at qguiapplication.cpp:1993:12
    frame #21: 0x0000000100004b59 apphelper`exitFromThread(argc=1, argv=0x00007ff7bfeff318) at apphelper.cpp:50:5
  thread #8, name = 'QThread'
...
    frame #11: 0x00007ff8020c4f94 dyld`dyld4::APIs::dlclose(void*) + 178
    frame #12: 0x0000000103e82476 QtCore`QLibraryPrivate::unload_sys(this=0x0000600001254160) at qlibrary_unix.cpp:252:24
    frame #13: 0x0000000103e793fc QtCore`QLibraryPrivate::unload(this=0x0000600001254160, flag=UnloadSys) at qlibrary.cpp:561:36
    frame #14: 0x00000001039740c8 QtCore`QFactoryLoader::~QFactoryLoader(this=0x00000001029e5e70) at qfactoryloader.cpp:438:21
    frame #15: 0x00000001039745e9 QtCore`QFactoryLoader::~QFactoryLoader(this=0x00000001029e5e70) at qfactoryloader.cpp:425:1
    frame #16: 0x0000000101eb723c QtGui`void std::__1::__destroy_at[abi:sn180100]<QFactoryLoader, 0>(__loc=0x00000001029e5e70) at construct_at.h:67:11
    frame #17: 0x0000000101eb7209 QtGui`void std::__1::destroy_at[abi:sn180100]<QFactoryLoader, 0>(__loc=0x00000001029e5e70) at construct_at.h💯3
    frame #18: 0x0000000102046762 QtGui`QtGlobalStatic::Storage<QFactoryLoader, (anonymous namespace)::Q_QGS_piLoader>::destroyYourself(nextState=Destroyed) at qglobalstatic.h:61:9
    frame #19: 0x0000000102046736 QtGui`QtGlobalStatic::Holder<(anonymous namespace)::Q_QGS_piLoader, (anonymous namespace)::Q_QGS_piLoader>::~Holder(this=0x00000001029e5e61) at qglobalstatic.h:83:9
    frame #20: 0x00000001020465d9 QtGui`QtGlobalStatic::Holder<(anonymous namespace)::Q_QGS_piLoader, (anonymous namespace)::Q_QGS_piLoader>::~Holder(this=0x00000001029e5e61) at qglobalstatic.h:82:5
    frame #21: 0x00007ff8022f4231 libsystem_c.dylib`__cxa_finalize_ranges + 402
    frame #22: 0x00007ff8022f4052 libsystem_c.dylib`exit + 35
    frame #23: 0x000000010000755a apphelper`exitFromThread(int, char**)::$_1::operator()(this=0x000060000175612c) const at apphelper.cpp:47:9

Change-Id: Ib1c72c7975b247cc2d17fffd6c5de89a95c22dad
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit e6a6757c1485d09a4b7a124d67260f06d8022fef)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 87c790851e9dad7d9f65e2582c047dddedbeb66a)
This commit is contained in:
Thiago Macieira 2025-03-05 09:59:24 -08:00 committed by Qt Cherry-pick Bot
parent 54555755f8
commit a1c85decc2

View File

@ -10,6 +10,12 @@
#include <stdlib.h>
#include <stdio.h>
#ifdef Q_OS_WIN
# include <io.h>
#else
# include <sys/types.h>
# include <unistd.h>
#endif
#if defined(QT_WIDGETS_LIB)
#include <QtWidgets/QApplication>
@ -23,6 +29,10 @@ using TestApplication = QGuiApplication;
using TestApplication = QCoreApplication;
#endif
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#include "maybeshow.h"
static int exitFromEventLoop(int argc, char **argv)
@ -42,7 +52,15 @@ static int exitFromThread(int argc, char **argv)
fprintf(stderr, "QThread::currentThread is null!\n");
::exit(EXIT_SUCCESS);
});
QTimer::singleShot(200, thr, [&thr] { thr->start(); });
QTimer::singleShot(200, thr, [&thr] {
thr->start();
// block the GUI forever, otherwise the unloading of the QPA plugins
// could cause a crash if something is running.
char c;
int r = read(STDIN_FILENO, &c, 1);
Q_UNUSED(r);
});
app.exec();
Q_UNREACHABLE_RETURN(EXIT_FAILURE);
}