This below was reported as a Qt bug 139361.
Found the Problem
Compiler mismatch with Posix
In narrowing down the problem to a certain version, the cause is probably related to a used toolchain. I've got 2 versions of v6.9.1, and one is broken. At first glance it looks like a GNU toolchain mismatch.
The cross-compiler on Linux seems to be posix one and the one I used on Windows a non-posix. Also the version on Linux was according the package a 13.2.
g++ --version (is broken)
g++.exe (GCC) 13.1.0 Copyright (C) 2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
g++ --version on Qt provided compiler (is working)
g++.exe (x86_64-posix-seh-rev1, Built by MinGW-Builds project) 13.1.0 Copyright (C) 2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Compiler version mismatch
Linux MinGW version is apparently v13.0.0 which is not a released version for Windows.
The Qt framework I built using Windows MinGW v13.2.0.
Before this was not a problem since stdc++-6.dll is designed to be forward compatible.
Still when starting the executable from Windows it could not link _ZSt21ios_base_library_initv from stdc++-6.dll
as where Wine could. (A Wine dynamic linker workaround used in is presumed).
It looks like the issue GCC Bugzilla – Bug 116159
is the cause of it all and seems to be solved in GCC v14.3 which is not available yet.
Custom Qt v6.9.1 causes SIGSEGV on exit
Context
I build the Qt Library (https://code.qt.io/qt/qt5.git tag: v6.9.1) myself for Ubuntu Linux (x86_64, aarch64) and Windows (x86_64) to include single Docker image to build all 3 targeted OS/architectures in a single CI/CD pipeline using a single Docker image.
The Windows app is cross-compiled from Linux using mingw and unittested using Wine from the Docker container as well.
The Windows Qt Framework is built natively on Windows 11.
Not the full Qt framework is built to keep small and thus the Docker
image.
(see attachment: config.summary)
Issue
After upgrading a working application from Qt v6.8.1 to v6.9.1 the application hung on exit in a destructor from a thread called "Thread(pooled)":
set_thread_data(QThreadData*)::Cleanup::~Cleanup()
Debugging Disassembly
set_thread_data(QThreadData*)::Cleanup::~Cleanup():
endbr64
push %rsi
push %rbx
sub $0x28,%rsp
lea 0x27762f(%rip),%rcx # 0x7fffe7a292e0 <__emutls_v._ZL17currentThreadData>
call 0x7fffe7947570 <__emutls_get_address>
mov (%rax),%rbx
mov %rax,%rsi
SIGSEGV signal on the next 'mov' instruction where '$rbx' seems to be a nullptr or uninitialized.
mov 0x50(%rbx),%rax
cmpb $0x0,0x8e(%rbx)
jne 0x7fffe77b1ce8 <set_thread_data(QThreadData*)::Cleanup::~Cleanup()+72>
lock subl $0x1,0x80(%rbx)
je 0x7fffe77b1d00 <set_thread_data(QThreadData*)::Cleanup::~Cleanup()+96>
movq $0x0,(%rsi)
add $0x28,%rsp
pop %rbx
pop %rsi
ret
nopl 0x0(%rax)
mov 0x8(%rax),%rcx
mov $0x1,%edx
call 0x7fffe77b19e0 <QThreadPrivate::finish(bool)>
jmp 0x7fffe77b1cc9 <set_thread_data(QThreadData*)::Cleanup::~Cleanup()+41>
nopl 0x0(%rax,%rax,1)
mov %rbx,%rcx
call 0x7fffe76f7560 <QThreadData::~QThreadData()>
mov $0x90,%edx
mov %rbx,%rcx
call 0x7fffe79461b0 <operator delete(void*, unsigned long long)>
movq $0x0,(%rsi)
add $0x28,%rsp
pop %rbx
pop %rsi
ret
nop
data16 cs nopw 0x0(%rax,%rax,1)
nop
File: qtbase/src/corelib/qthread_win.cpp:86
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;
}
currentThreadData = data;
}
Isolation Steps
1) Single File Test Application
I isolated the problem a created a simple application causing the problem when a QPushButton instance not parented by a QWidget.
#include <QApplication>
#include <QDebug>
#include <QPushButton>
int main(int argc, char* argv[])
{
int rv{0};
QApplication app(argc, argv);
QWidget* wgt{nullptr};
if (argc == 1)
// Makes it hang when application exists. When debugging causes a SIGSEGV signal.
wgt = new QPushButton(QString(qVersion()) + "/" + QT_VERSION_STR);
else
// Seems to be no problem.
wgt = new QWidget();
wgt->setWindowTitle("Qt Test Application");
wgt->resize(300, 120);
wgt->show();
rv = app.exec();
delete wgt;
qDebug() << "Exiting with code:" << rv;
return rv;
}
2) Compiler
To be sure the compiler MinGW-w64-x86_64-13.1.0-release-posix-seh-msvcrt-rt_v11-rev1.7z was downloaded from Qt to build the framework.
3) Using Pre-build Windows Qt v6.9.1 Framework
To narrow the problem down I used the downloaded the prebuild Qt v6.9.1
full framework.
This does NOT seem to cause the issue.
Reproduce
To build the Qt framework I use a single bash script build-qt-lib.sh (qt-v6.9.1-core-bug.zip) also used from Windows in a Cygwin environment.
My Conclusion
Although I have not compiled the complete framework myself (takes a really long time) it seems omitting components introduces a bug that version v6.8.1 did not have using the same components building the framework subset.