Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.9.1
-
None
-
a32cf1a22d096b33340cddbe91328c6c088e221d
Description
In Qt Quick Controls 2, we want to make Button backgrounds etc. deferred properties to avoid unnecessarily executing the default background when the background is overridden with a custom background.
qtquickcontrols2/Button.qml:
T.Button { implicitWidth: background.implicitWidth // depency background: Rectangle { ... } // deferred }
// usercode1.qml
Button {
background: Rectangle { ... } // overrides
}
So far, so good. This is already working as desired. Problems arise if the deferred background property is not overridden, but accessed as a grouped property instead:
usercode2.qml
Button { background.visible: false // boom }
Due to the dependent binding, this leads to an infinite loop qmlExecuteDeferred() => QQmlObjectCreator::setupBindings() => qmlExecuteDeferred().
A minimal testcase:
#include <QtQml> class DeferredType : public QObject { Q_OBJECT Q_PROPERTY(QObject *deferredObject READ deferredObject WRITE setDeferredObject NOTIFY deferredObjectChanged) Q_CLASSINFO("DeferredPropertyNames", "deferredObject") public: DeferredType(QObject *parent = nullptr) : QObject(parent) { } QObject *deferredObject() const { if (!m_deferredObject) qmlExecuteDeferred(const_cast<DeferredType *>(this)); return m_deferredObject; } void setDeferredObject(QObject *object) { if (m_deferredObject == object) return; delete m_deferredObject; m_deferredObject = object; emit deferredObjectChanged(); } signals: void deferredObjectChanged(); private: QObject *m_deferredObject = nullptr; }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qmlRegisterType<DeferredType>("main", 1, 0, "DeferredType"); QQmlEngine engine; QQmlComponent component(&engine); component.setData("import main 1.0; DeferredType { deferredObject.objectName: 'foo'; objectName: deferredObject.objectName }", QUrl()); component.create(); // BOOM } #include "main.moc"
Relevant part of the stacktrace:
Thread 1 "untitled811" received signal SIGSEGV, Segmentation fault. 0x0000000000401da4 in DeferredType::qt_static_metacall (_o=<error reading variable: Cannot access memory at address 0x7fffff7fefe8>, _c=<error reading variable: Cannot access memory at address 0x7fffff7fefe4>, _id=<error reading variable: Cannot access memory at address 0x7fffff7fefe0>, _a=<error reading variable: Cannot access memory at address 0x7fffff7fefd8>) at ./main.moc:78 78 { (gdb) bt #0 0x0000000000401da4 in DeferredType::qt_static_metacall (_o=<error reading variable: Cannot access memory at address 0x7fffff7fefe8>, _c=<error reading variable: Cannot access memory at address 0x7fffff7fefe4>, _id=<error reading variable: Cannot access memory at address 0x7fffff7fefe0>, _a=<error reading variable: Cannot access memory at address 0x7fffff7fefd8>) at ./main.moc:78 #1 0x000000000040200b in DeferredType::qt_metacall (this=0x668e10, _c=QMetaObject::ReadProperty, _id=0, _a=0x7fffff7ff0e0) at ./main.moc:156 #2 0x00007f3bdd4a2388 in QMetaObject::metacall (object=<optimized out>, cl=cl@entry=QMetaObject::ReadProperty, idx=<optimized out>, argv=argv@entry=0x7fffff7ff0e0) at kernel/qmetaobject.cpp:301 #3 0x00007f3bddaa1d3f in QQmlObjectCreator::setPropertyBinding (this=this@entry=0x95ea60, property=property@entry=0x7f3bcc0054c8, binding=binding@entry=0x7f3bcc00b218) at qml/qqmlobjectcreator.cpp:781 #4 0x00007f3bddaa3662 in QQmlObjectCreator::setupBindings (this=this@entry=0x95ea60, applyDeferredBindings=applyDeferredBindings@entry=true) at qml/qqmlobjectcreator.cpp:703 #5 0x00007f3bddaa3a61 in QQmlObjectCreator::populateDeferredProperties (this=0x95ea60, instance=0x0, instance@entry=0x668e10) at qml/qqmlobjectcreator.cpp:273 #6 0x00007f3bdda10a08 in QQmlComponentPrivate::beginDeferred (enginePriv=enginePriv@entry=0x623700, object=object@entry=0x668e10, state=state@entry=0x7fffff7ff480) at qml/qqmlcomponent.cpp:892 #7 0x00007f3bdd9f752a in QtQml::qmlExecuteDeferred (object=0x668e10) at qml/qqmlengine.cpp:1467 #8 0x0000000000402539 in DeferredType::deferredObject (this=0x668e10) at ../untitled811/main.cpp:15 #9 0x0000000000401e77 in DeferredType::qt_static_metacall (_o=0x668e10, _c=QMetaObject::ReadProperty, _id=0, _a=0x7fffff7ff5f0) at ./main.moc:103 #10 0x000000000040200b in DeferredType::qt_metacall (this=0x668e10, _c=QMetaObject::ReadProperty, _id=0, _a=0x7fffff7ff5f0) at ./main.moc:156 #11 0x00007f3bdd4a2388 in QMetaObject::metacall (object=<optimized out>, cl=cl@entry=QMetaObject::ReadProperty, idx=<optimized out>, argv=argv@entry=0x7fffff7ff5f0) at kernel/qmetaobject.cpp:301 #12 0x00007f3bddaa1d3f in QQmlObjectCreator::setPropertyBinding (this=this@entry=0x95e880, property=property@entry=0x7f3bcc0054c8, binding=binding@entry=0x7f3bcc00b218) at qml/qqmlobjectcreator.cpp:781 #13 0x00007f3bddaa3662 in QQmlObjectCreator::setupBindings (this=this@entry=0x95e880, applyDeferredBindings=applyDeferredBindings@entry=true) at qml/qqmlobjectcreator.cpp:703 #14 0x00007f3bddaa3a61 in QQmlObjectCreator::populateDeferredProperties (this=0x95e880, instance=0x0, instance@entry=0x668e10) at qml/qqmlobjectcreator.cpp:273 #15 0x00007f3bdda10a08 in QQmlComponentPrivate::beginDeferred (enginePriv=enginePriv@entry=0x623700, object=object@entry=0x668e10, state=state@entry=0x7fffff7ff990) at qml/qqmlcomponent.cpp:892 #16 0x00007f3bdd9f752a in QtQml::qmlExecuteDeferred (object=0x668e10) at qml/qqmlengine.cpp:1467
Attachments
Issue Links
- relates to
-
QTBUG-98439 "Binding on contentItem is not deferred as requested by the DeferredPropertyNames class info because it constitutes a group property" when instantiating ScrollBar
-
- Closed
-
- resulted from
-
QTBUG-50992 QQC2: Object destroyed during incubation
-
- Closed
-
For Gerrit Dashboard: QTBUG-63036 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
204740,2 | Disable deferring when referenced as a grouped property | 5.9 | qt/qtdeclarative | Status: MERGED | +2 | 0 |