Segmentation fault when exiting when linked against Qt 6.9.1
-
I really have no idea why this happens. Neither my
MainWindow
class, nor any of theQDockWidgets
shown even have a destructor, so I don't even have the chance to delete something that should not be deleted …The
MainWindow
catches acloseEvent
though. I set a break point there and stepped through what happens. The whole function exits like it should. No problem …The crash happens really late, after everything seems to be already cleaned up:
QCoreApplication::exec () at /home/tobias/Qt/qtbase-everywhere-src-6.9.1/src/corelib/kernel/qcoreapplication.cpp:1450 1450 threadData->quitNow = false; (gdb) n 1452 if (self) (gdb) n 1453 self->d_func()->execCleanup(); (gdb) n 1455 return returnCode; (gdb) n main (argc=1, argv=0x7fffffffd178) at /home/tobias/tmp/git/muckturnier/src/main.cpp:130 130 } (gdb) n Thread 1 "muckturnier" received signal SIGSEGV, Segmentation fault. 0x0000555555a55b76 in removeWidgetRecursively (li=<optimized out>, w=0x5555571eec40) at /home/tobias/Qt/qtbase-everywhere-src-6.9.1/src/widgets/kernel/qlayout.cpp:474 474 if (child->widget() == w) { (gdb) n [Thread 0x7ffff49e7900 (LWP 10439) exited] [Thread 0x7ffff45ff6c0 (LWP 10442) exited] [New process 10439] Program terminated with signal SIGSEGV, Segmentation fault. The program no longer exists.
Line 130 of my
main.cpp
is at the very end, afterreturn application.exec()
:129 return application.exec(); 130 } 131
Does this help?!
-
I really have no idea why this happens. Neither my
MainWindow
class, nor any of theQDockWidgets
shown even have a destructor, so I don't even have the chance to delete something that should not be deleted …The
MainWindow
catches acloseEvent
though. I set a break point there and stepped through what happens. The whole function exits like it should. No problem …The crash happens really late, after everything seems to be already cleaned up:
QCoreApplication::exec () at /home/tobias/Qt/qtbase-everywhere-src-6.9.1/src/corelib/kernel/qcoreapplication.cpp:1450 1450 threadData->quitNow = false; (gdb) n 1452 if (self) (gdb) n 1453 self->d_func()->execCleanup(); (gdb) n 1455 return returnCode; (gdb) n main (argc=1, argv=0x7fffffffd178) at /home/tobias/tmp/git/muckturnier/src/main.cpp:130 130 } (gdb) n Thread 1 "muckturnier" received signal SIGSEGV, Segmentation fault. 0x0000555555a55b76 in removeWidgetRecursively (li=<optimized out>, w=0x5555571eec40) at /home/tobias/Qt/qtbase-everywhere-src-6.9.1/src/widgets/kernel/qlayout.cpp:474 474 if (child->widget() == w) { (gdb) n [Thread 0x7ffff49e7900 (LWP 10439) exited] [Thread 0x7ffff45ff6c0 (LWP 10442) exited] [New process 10439] Program terminated with signal SIGSEGV, Segmentation fault. The program no longer exists.
Line 130 of my
main.cpp
is at the very end, afterreturn application.exec()
:129 return application.exec(); 130 } 131
Does this help?!
-
@Axel-Spoerl : dockwidgets... 😛
-
The problem is that the only custom thing I do is the
closeEvent
override – everything else happens inside the default Qt code … and even if I remove the customcloseEvent
, the segfault is the same (which is not really surprising, when I stepped through everything that happens, the function returns, and the crash happens way later, while we're long deep inside Qt …).@Christian-Ehrlicher : May I suppose from what you wrote that this is not the first time strange things happen when dock widgets are messed with?! ;-)
The only thing I can definitely say is that some change from 6.9.0 to 6.9.1 causes this, because it never happens with 6.9.0, and it always happens with 6.9.1 …
-
Luckily, my desktop is still quite decent, so I could git bisect out the commit that introduced this.
If I checkout
commit 19c4db4201e8933fbbbf951809ceff30e99b4458 QDockWidget: don't access a QMainWindow that's under destruction
everything is fine, no crash. One commit later, at
commit ab6f1ad77852a427ae73172ca11dacf876a0cbf7 QMainWindowLayout: Fix leaking of unused tab bars
I get the segfault.
I would call it a regression …
-
Ooops, I am guilty for the guilty commit!
What's obviously crashing is a
QDockWidget
. Can you tell us more about those?
How are they added? how isQDockWidget::setWidget()
used? In which state are they, when the crash occurs (docked on the main window / Floating / Tabbed)? -
@Axel-Spoerl Hi, nice to meet the right guy at once ;-)
I meanwhile filed a bug report about this: https://bugreports.qt.io/browse/QTBUG-137755
For all dock widgets I first instatiate a widget, like this (all are simple
QWidgets
– with quite complex stuff inside, but still):m_registrationPage = new RegistrationPage(this, m_sharedObjects); ...
then, I create the dock, format it, set the widget and hide it, like this:
m_playersDock = new QDockWidget(tr("Anmeldung"), this); m_playersDock->setWidget(m_registrationPage); formatDockWidget(m_playersDock, QStringLiteral("playersDock")); addDockWidget(Qt::TopDockWidgetArea, m_playersDock); connect(m_registrationPage, &RegistrationPage::raiseMe, m_playersDock, &QDockWidget::raise); m_playersDock->hide();
Where the formatting is:
void MainWindow::formatDockWidget(QDockWidget *dock, const QString &id) { dock->setObjectName(id); dock->setContextMenuPolicy(Qt::PreventContextMenu); dock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); }
When I start the program, all docks are hidden. If I close it again in this state, I get no segfault.
Opening a database makes them show up, by default attached to the main window and tabbed. When closing the program then, the segfault happens.
Interestingly, if I close my database again, the docks are hidden again – but still, I get a segfault on closing.
-
Hm. Looks like I went too far and we have to revert or follow up on this patch.
Can you do me a favor: Report it as a bug, assign it to me? I'll fix it this week. -
I already filed one here: https://bugreports.qt.io/browse/QTBUG-137755 – I can't assign it to you though (or better said, I don't know how to do that …)
Somebody already commented on it, and mentioned these two PRs:
https://codereview.qt-project.org/c/qt/qtbase/+/637198
https://codereview.qt-project.org/c/qt/qtbase/+/636652 -
I already filed one here: https://bugreports.qt.io/browse/QTBUG-137755 – I can't assign it to you though (or better said, I don't know how to do that …)
Somebody already commented on it, and mentioned these two PRs:
https://codereview.qt-project.org/c/qt/qtbase/+/637198
https://codereview.qt-project.org/c/qt/qtbase/+/636652 -
Just to also leave this here: I meanwhile could strip it down to a minimal example producing the crash, cf. the sources attached to https://bugreports.qt.io/browse/QTBUG-137755
Produces the crash reliably when linked against Qt 6.9.1. You have to run the program twice: The first time, it exits normally. The second time, when the window geometry and state are restored, it segfaults on exiting.
No delete, no deleteLater, nothing special at all …
-
Great reproducer!
Someone decades ago felt like storing unused tab bars for later re-usage inQMainWindowLayout
.
Those were soft-leaked and taken care off, whenQApplication
got destroyed.
Reading the state back from settings causes the original tab bar (created in the C++ part) to become unused, but not removed from itsQMainWindow
parent. That ultimately lead to a double delete and the crash.
Let's see, if my thorough reviewers let me get away without writing an autotest ;-) -
Wow, that was fast :-) Thanks for the immediate fix! Nice to see my stuff helped here!
That was quite deep inside Qt apparently … where will this land? Qt 6.10.0? Or will it be backported?
I tried to cherry-pick it to a 6.9.1 checkout to test it, but it seems that's no trivial task …
-
Wow, that was fast :-) Thanks for the immediate fix! Nice to see my stuff helped here!
That was quite deep inside Qt apparently … where will this land? Qt 6.10.0? Or will it be backported?
I tried to cherry-pick it to a 6.9.1 checkout to test it, but it seems that's no trivial task …
-
Ah okay. So no 6.9 backport? I just wondered, because in the respective "Change ID" https://codereview.qt-project.org/c/qt/qtbase/+/653727, it's listed: "Fixes: QTBUG-137755 Pick-to: 6.10 6.9"
-
Ah okay. So no 6.9 backport? I just wondered, because in the respective "Change ID" https://codereview.qt-project.org/c/qt/qtbase/+/653727, it's listed: "Fixes: QTBUG-137755 Pick-to: 6.10 6.9"
-
The fix will land in 6.9.2, which we plan to release on August 14th.
If you want to cherry pick and compile locally, please make sure to pick the following 5 commits in the right order: