diff options
Diffstat (limited to 'src/widgets')
-rw-r--r-- | src/widgets/widgets/qmenu.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index fe5c52ee93..6198b8bfa1 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -571,6 +571,35 @@ void QMenuPrivate::hideMenu(QMenu *menu) { if (!menu) return; + + // See two execs below. They may trigger an akward situation + // when 'menu' (also known as 'q' or 'this' in the many functions + // around) to become a dangling pointer if the loop manages + // to execute 'deferred delete' ... posted while executing + // this same loop. Not good! + struct Reposter : QObject + { + Reposter(QMenu *menu) : q(menu) + { + Q_ASSERT(q); + q->installEventFilter(this); + } + ~Reposter() + { + if (deleteLater) + q->deleteLater(); + } + bool eventFilter(QObject *obj, QEvent *event) override + { + if (obj == q && event->type() == QEvent::DeferredDelete) + return deleteLater = true; + + return QObject::eventFilter(obj, event); + } + QMenu *q = nullptr; + bool deleteLater = false; + }; + #if QT_CONFIG(effects) QSignalBlocker blocker(menu); aboutToHide = true; @@ -582,6 +611,7 @@ void QMenuPrivate::hideMenu(QMenu *menu) QAction *activeAction = currentAction; menu->setActiveAction(nullptr); + const Reposter deleteDeleteLate(menu); QTimer::singleShot(60, &eventLoop, SLOT(quit())); eventLoop.exec(); |