Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-107850

Crash on QQuickItem destruction

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P1: Critical
    • 6.5.0 FF
    • 5.15.7
    • Quick: Other
    • None
    • All

    Description

      Crash on destruction of item based on QQuickItem.

      Crash happens in case when item or children of the item have CPP bindings to  parentChanged/visibleChanged signals (signals of child items or item) and virtual function of the destroying item called in connected cpp slot.

      Current implementation of ~QQuckItem() emits signals

      • parentChanged for item and children items
      • visibleChanged  for item and children items in case when item was invisible before destruction  

      When the slot (on someChild.VisibleChanged) is called developer does not expect that the signal was called during destruction of the item, so any function of item (stored as member/QPointer, for example) can be called and crash the app.

      stack trace on the crash:

      deleted item -> ~MyItem -> ~QQuckItem -> setParent(nullptr) -> QQuickItemPrivate::setEffectiveVisibleRecur for children -> parentChanged / visibleChanged in child -> Slot with call of item virtual function -> SEGFAULT

      Pointer to that item is still valid in the slot.

      Isolated example:

      class ItemForTesting: public QQuickItem {
          Q_OBJECT
      public:
          explicit ItemForTesting(QQuickItem *parent = nullptr);
          ~ItemForTesting() override = default;
          virtual void setMember(int val);
          int m_member;
      };
      
      ItemForTesting::ItemForTesting(QQuickItem *parent)
          : QQuickItem(parent)
          , m_member(0)
      {}
      void ItemForTesting::setMember(int val)
      {
          m_member = val;
      }
      //// Test case
      {
      ....
          QPointer<ItemForTesting> mainItem = new ItemForTesting(m_rootItem);
          mainItem->setVisible(false); // in this case visibleChanged will be emitted for item and for child items
          mainItem->connect(mainItem.data(), &QQuickItem::parentChanged, mainItem.data(), [=]() {
              qCritical() << "ParentChanged for mainItem. Check pointer" << QQmlData::wasDeleted(mainItem.data()) << mainItem.isNull();
              // mainItem->setMember(2); // possible crash is here
          });
      
          QQuickItem *childItem = new QQuickItem(mainItem);
          childItem->connect(childItem, &QQuickItem::visibleChanged, childItem, [=, &mainItem]() {
              qCritical() << "visibleChanged for childItem to" << childItem->isVisible() << ". Check pointer of mainItem" << QQmlData::wasDeleted(mainItem.data()) << mainItem.isNull();
              mainItem->setMember(2); // Crash is here
          });
      
          QSignalSpy spyDestroy(mainItem, &QObject::destroyed);
          mainItem->deleteLater();
          spyDestroy.wait();
          EXPECT_EQ(spyDestroy.count(), 1);
      }
      

       

      the main problem here - calling of virtual function during destruction.

      But in current implementation of ~QQuickItem, developer of ItemForTesting class could not grantee that virtual function of ItemForTesting will not be called during destruction of the ItemForTesting instance, even if developer does not call virtual function in the destructor directly. It can be called indirectly in children via signals-slots during ~QQuickItem.

      Potentially, any component with virtual function can crash app in this case (because of unexpected signals).

      Attached example qtbug107850_extended.ziphas 3 options: 

      1. to change visible for mainItem created in QML 
      2. to call deleting of mainItem created in QML  -> in case if mainItem had visible = false (default case in this example) before the deletion it crashes.
      3. to call Cpp crash case (like mentioned in the ticket description)

      pressing on 2 -> crash

      pressing on 3 -> crash

      pressing on 1, then 2 -> no crash

      Attachments

        1. QTBUG-107850_2.tar.gz
          0.8 kB
          Fabian Kosmale
        2. qtbug107850_extended.zip
          3 kB
          Ivan Maiornykov
        3. qtbug107850.tar.gz
          2 kB
          Volker Hilsheimer

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              vhilshei Volker Hilsheimer
              mjnikoff Ivan Maiornykov
              Votes:
              2 Vote for this issue
              Watchers:
              11 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews