Details
-
Bug
-
Resolution: Fixed
-
P1: Critical
-
6.5.4
-
None
-
47b4037cc (dev), a2de295be (6.6), 8ec96b617 (tqtc/lts-6.5)
Description
When aborting incubation using QQmlIncubator, QQuickContainer references an already deleted item. Backtrace:
QQuickContainerPrivate::itemAt(int) const (@QQuickContainerPrivate::itemAt(int) const:9) QQuickContainerPrivate::cleanup() (@QQuickContainerPrivate::cleanup():23) QQuickContainer::~QQuickContainer() (@QQuickContainer::~QQuickContainer():12) ___lldb_unnamed_symbol8599 (@___lldb_unnamed_symbol8599:17) QQmlObjectCreator::clear() (@QQmlObjectCreator::clear():110) QQmlIncubatorPrivate::clear() (@QQmlIncubatorPrivate::clear():104) QQmlIncubator::clear() (@QQmlIncubator::clear():30) QQmlIncubatorPrivate::clear() (@QQmlIncubatorPrivate::clear():122) QQmlIncubator::clear() (@QQmlIncubator::clear():30) X::abortIncubation(X*) ...
Sample QML file that causes the crash.
import QtQuick import QtQuick.Layouts import QtQuick.Controls Item { Repeater { model: 100 // Repeat so the panel doesn't incubate immediately - we need to abort while it's still loading. TabBar { id: bar width: parent.width TabButton { text: qsTr("Home") } TabButton { text: qsTr("Discover") } TabButton { text: qsTr("Activity") } } } }
Test harness code:
#include <QFile> #include <QGuiApplication> #include <QQmlComponent> #include <QQmlEngine> #include <QQmlIncubator> #include <QTimer> #include <iostream> void testIncubation(QQmlIncubationController& controller) { for (int i = 0; i < 1000; i++) { QQmlIncubator incubator; QQmlComponent component(controller.engine(), QUrl("qrc:/main.qml")); if (component.isError()) { for (const auto& error : component.errors()) { std::cerr << error.toString().toStdString() << std::endl; } exit(-1); } component.create(incubator); controller.incubateFor(i); if (controller.incubatingObjectCount() == 0) { std::cout << "We've incubated for " << i << " and the component is fully loaded now." << std::endl; break; } incubator.clear(); } } int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); QQmlEngine engine; QQmlIncubationController controller; engine.setIncubationController(&controller); QTimer::singleShot(1, [&]() { testIncubation(controller); app.exit(0); }); return app.exec(); }