The event filter was still active when the QDialogButtonBox in its destruction process had already been demoted to QWidget. The ignoreShowAndHide guard came too late, because by the time we check it, in Private::handleButtonShowAndHide(), we had already cast q_ptr to QDialogButtonBox. Says UBSan: qdialogbuttonbox_p.h:26:5: runtime error: downcast of address 0x7fffefab47e0 which does not point to an object of type 'QDialogButtonBox' 0x7fffefab47e0: note: object is of type 'QWidget' 00 00 00 00 28 c1 5b 6e 6d 7f 00 00 80 22 10 00 90 61 00 00 d8 c2 5b 6e 6d 7f 00 00 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QWidget' #0 0x7f6d6b51141d in QDialogButtonBoxPrivate::q_func() qdialogbuttonbox_p.h:26 #1 0x7f6d6b51141d in QDialogButtonBoxPrivate::handleButtonShowAndHide(QAbstractButton*, QEvent*) qdialogbuttonbox.cpp:913 #2 0x7f6d6b51436c in eventFilter qdialogbuttonbox.cpp:127 #3 0x7f6d40c1a8f1 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) qcoreapplication.cpp:1248 #4 0x7f6d690b23d5 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3303 #5 0x7f6d69132a3a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259 #6 0x7f6d40c1da6a in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111 #7 0x7f6d40c20473 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.cpp:1551 #8 0x7f6d690fe76c in QApplicationPrivate::setActiveWindow(QWidget*) qapplication.cpp:1857 #9 0x7f6d695ac796 in QWidgetPrivate::deactivateWidgetCleanup() qwidget.cpp:2326 #10 0x7f6d6976f8ce in QWidgetPrivate::hide_sys() qwidget.cpp:8256 #11 0x7f6d69814579 in QWidgetPrivate::hide_helper() qwidget.cpp:8199 #12 0x7f6d69887c1f in QWidgetPrivate::setVisible(bool) qwidget.cpp:8406 #13 0x7f6d69775d23 in QWidget::setVisible(bool) qwidget.cpp:8314 #14 0x7f6d695fb018 in QWidget::hide() qwidget.cpp:8179 #15 0x7f6d6981a183 in QWidgetPrivate::handleClose(QWidgetPrivate::CloseMode) qwidget.cpp:8580 #16 0x7f6d699e6fc6 in QWidgetWindow::closeEvent(QCloseEvent*) qwidgetwindow.cpp:871 #17 0x7f6d52ef9f5d in QWindow::event(QEvent*) qwindow.cpp:2721 #18 0x7f6d69a575f8 in QWidgetWindow::event(QEvent*) qwidgetwindow.cpp:398 #19 0x7f6d690b2491 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3309 #20 0x7f6d69132a3a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3259 #21 0x7f6d40c1da6a in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:1111 #22 0x7f6d40c205b3 in QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) qcoreapplication.cpp:1565 #23 0x7f6d5287415b in QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent*) qguiapplication.cpp:2911 #24 0x7f6d528b543f in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) qguiapplication.cpp:2259 #25 0x7f6d52fb5b02 in QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) qwindowsysteminterface.cpp:190 #26 0x7f6d52fb5b02 in bool QWindowSystemHelper<QWindowSystemInterface::SynchronousDelivery>::handleEvent<QWindowSystemInterfacePrivate::CloseEvent, QWindow*>(QWindow*) qwindowsysteminterface.cpp:102 #27 0x7f6d52fb5b02 in handleWindowSystemEvent<QWindowSystemInterfacePrivate::CloseEvent, QWindowSystemInterface::SynchronousDelivery, QWindow*> qwindowsysteminterface.cpp:138 #28 0x7f6d52fb5b02 in bool QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::SynchronousDelivery>(QWindow*) qwindowsysteminterface.cpp:351 #29 0x7f6d52cb6f1e in QPlatformWindow::close() qplatformwindow.cpp:348 #30 0x7f6d52e7e158 in QWindow::close() qwindow.cpp:2449 #31 0x7f6d6981b4d2 in QWidgetPrivate::close() qwidget.cpp:8632 #32 0x7f6d698205c6 in QWidget::~QWidget() qwidget.cpp:1508 #33 0x7f6d6b4f6bf0 in QDialogButtonBox::~QDialogButtonBox() qdialogbuttonbox.cpp:496 To fix, don't delay the Q_Q to until after the ignoreShowAndHide check, since that woould be brittle. Instead, do as we for signal/slot connections, which we disconnect explicitly in ~QDialogButtonBox(), and delete the EventFilter explicitly there, too. This way, it's more natural, and also prevents all those useless event filter invocations from having to be processed later on. Amends aff0915352dda0cfaa11a249b665fbe47be21d69. The original code, using QDialogButtonBox::eventFilter(), was not affected, since by the time QDialogButtonBox was demoted to QWidget, QWidget::eventFilter(), not QDialogButtonBox::eventFilter() would been invoked. Which just goes to show that one needs to be very careful with delegating too much responsibilites to the Private class, as it lives, fully derived, until ~QWidget() executes. Pick-to: 6.9 6.8 6.5 Change-Id: I04f36fd6d7d160932bfe1494fdff464786b85047 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
…
…
Description
Languages
C++
84.3%
HTML
4.9%
C
3.9%
CMake
3.6%
Objective-C++
2%
Other
0.8%