aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2018-05-04 13:29:45 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2018-05-04 11:56:00 +0000
commita5d2731b1ec56580a79784759307d3b3c21ab87f (patch)
tree04b69e88d8fbf4456170a47831f32e25927c7998 /src
parent1274fa1f799db688b7acdfac216c54cd3dc277f3 (diff)
Fix QQuickPopupPositioner
This is a double-regression caused by commits bcd1bed and 03a8c88. Both of these changes caused dangling pointers being left on the list of item change listeners. First, bcd1bed made QQuickPopupPositioner use QQuickItem::isAncestorOf() without noticing the difference that the old self-made isAncestorOf() conveniently returned true for the item itself, whereas the new built-in QQuickItem::isAncestorOf() doesn't. This had a nasty side effect that when the popup's parent item was removed from its parent, QQuickPopupPositioner::itemChildRemoved() no longer removed the ancestor listeners. Then, 03a8c88 made things worse by changing the stack allocation of QQuickPopupPositioner to heap allocation without ever deleting the positioner object. Valgrind output for tst_tooltip: ==14391== Invalid read of size 8 ==14391== at 0x79EFB9A: QQuickItemPrivate::itemChange(QQuickItem::ItemChange, QQuickItem::ItemChangeData const&) (qquickitem.cpp:6206) ==14391== by 0x79F3D98: QQuickItem::setParentItem(QQuickItem*) (qquickitem.cpp:2791) ==14391== by 0x79F3E87: QQuickItem::~QQuickItem() (qquickitem.cpp:2385) ==14391== by 0x7A16073: ~QQmlElement (qqmlprivate.h:103) ==14391== by 0x7A16073: QQmlPrivate::QQmlElement<QQuickItem>::~QQmlElement() (qqmlprivate.h:103) ==14391== by 0x7A9CFEE: QQuickView::~QQuickView() (qquickview.cpp:218) ==14391== by 0x4038215: quick_test_main_with_setup(int, char**, char const*, char const*, QObject*) (quicktest.cpp:512) ==14391== by 0x4038CFF: quick_test_main(int, char**, char const*, char const*) (quicktest.cpp:330) ==14391== by 0x400BD7: main (tst_default.cpp:44) ==14391== Address 0x1f2d3f10 is 0 bytes inside a block of size 32 free'd ==14391== at 0x4C2F29C: operator delete(void*) (vg_replace_malloc.c:576) ==14391== by 0x29CA2641: QQuickPopupPositioner::~QQuickPopupPositioner() (qquickpopuppositioner.cpp:68) ==14391== by 0x29CA004C: QQuickPopup::~QQuickPopup() (qquickpopup.cpp:783) ==14391== by 0x2A1A4CEE: ~QQuickToolTip (qquicktooltip_p.h:59) ==14391== by 0x2A1A4CEE: ~QQmlElement (qqmlprivate.h:103) ==14391== by 0x2A1A4CEE: QQmlPrivate::QQmlElement<QQuickToolTip>::~QQmlElement() (qqmlprivate.h:103) ==14391== by 0x6397A65: QObjectPrivate::deleteChildren() (qobject.cpp:1997) ==14391== by 0x6398DDA: QObject::~QObject() (qobject.cpp:1025) ==14391== by 0x79F41FA: QQuickItem::~QQuickItem() (qquickitem.cpp:2378) ==14391== by 0x7A897D5: QQuickMouseArea::~QQuickMouseArea() (qquickmousearea.cpp:452) ==14391== by 0x7A1699D: ~QQmlElement (qqmlprivate.h:103) ==14391== by 0x7A1699D: QQmlPrivate::QQmlElement<QQuickMouseArea>::~QQmlElement() (qqmlprivate.h:103) ==14391== by 0x639082D: qDeleteInEventHandler(QObject*) (qobject.cpp:4603) ==14391== by 0x6392478: QObject::event(QEvent*) (qobject.cpp:1242) ==14391== by 0x79F1D77: QQuickItem::event(QEvent*) (qquickitem.cpp:8006) ==14391== Block was alloc'd at ==14391== at 0x4C2E226: operator new(unsigned long) (vg_replace_malloc.c:334) ==14391== by 0x29C9F939: QQuickPopupPrivate::init() (qquickpopup.cpp:280) ==14391== by 0x29C9FD4E: QQuickPopup::QQuickPopup(QQuickPopupPrivate&, QObject*) (qquickpopup.cpp:771) ==14391== by 0x29CC6CBB: QQuickToolTip::QQuickToolTip(QQuickItem*) (qquicktooltip.cpp:171) ==14391== by 0x2A1A58DD: QQmlElement (qqmlprivate.h:98) ==14391== by 0x2A1A58DD: void QQmlPrivate::createInto<QQuickToolTip>(void*) (qqmlprivate.h:107) ==14391== by 0x5D0186D: QQmlType::create(QObject**, void**, unsigned long) const (qqmlmetatype.cpp:915) ==14391== by 0x5D81EFF: QQmlObjectCreator::createInstance(int, QObject*, bool) (qqmlobjectcreator.cpp:1163) ==14391== by 0x5D85AE2: QQmlObjectCreator::create(int, QObject*, QQmlInstantiationInterrupt*) (qqmlobjectcreator.cpp:203) ==14391== by 0x5D82230: QQmlObjectCreator::createInstance(int, QObject*, bool) (qqmlobjectcreator.cpp:1202) ==14391== by 0x5D82F65: QQmlObjectCreator::setPropertyBinding(QQmlPropertyData const*, QV4::CompiledData::Binding const*) (qqmlobjectcreator.cpp:825) ==14391== by 0x5D85105: QQmlObjectCreator::setupBindings(bool) (qqmlobjectcreator.cpp:777) ==14391== by 0x5D857C5: QQmlObjectCreator::populateInstance(int, QObject*, QObject*, QQmlPropertyData const*) (qqmlobjectcreator.cpp:1456) Change-Id: Id368e79146f4673708a84253a009fcdf24ab4a2c Reviewed-by: J-P Nurmi <jpnurmi@qt.io> Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/quicktemplates2/qquickpopup.cpp2
-rw-r--r--src/quicktemplates2/qquickpopuppositioner.cpp2
2 files changed, 3 insertions, 1 deletions
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index e3ab952d..a481805f 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -775,6 +775,8 @@ QQuickPopup::~QQuickPopup()
d->popupItem->ungrabShortcut();
delete d->popupItem;
d->popupItem = nullptr;
+ delete d->positioner;
+ d->positioner = nullptr;
}
/*!
diff --git a/src/quicktemplates2/qquickpopuppositioner.cpp b/src/quicktemplates2/qquickpopuppositioner.cpp
index 2b67c85e..f2d02df1 100644
--- a/src/quicktemplates2/qquickpopuppositioner.cpp
+++ b/src/quicktemplates2/qquickpopuppositioner.cpp
@@ -248,7 +248,7 @@ void QQuickPopupPositioner::itemParentChanged(QQuickItem *, QQuickItem *parent)
void QQuickPopupPositioner::itemChildRemoved(QQuickItem *item, QQuickItem *child)
{
- if (child->isAncestorOf(m_parentItem))
+ if (child == m_parentItem || child->isAncestorOf(m_parentItem))
removeAncestorListeners(item);
}