summaryrefslogtreecommitdiffstats
path: root/src/widgets/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/widgets')
-rw-r--r--src/widgets/widgets/qmenu.cpp30
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();