aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlengine.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-11-24 09:41:09 +0100
committerUlf Hermann <ulf.hermann@qt.io>2022-11-24 20:38:39 +0100
commit60a18929027cca06fb81d007e81c056465507946 (patch)
tree6654d9f9d08761fc9e74936ddcba2e3cbf0b8f6b /src/qml/qml/qqmlengine.cpp
parent0e4acad6ab3a4caf02a4b372152e646f0c11c68d (diff)
QML: Monkey-patch thread safety issue with dynamic metaobjects
Not deleting the dynamic metaobject should at least prevent the crashes in the CI that have appeared lately. We can still race for the validity flag this way. While this is still technically UB, in practice it will work. We may yet find a better solution to this. Amends commit 3ba1496a65a06b38ee324b5ac10ffec98b22b0c1. Change-Id: I512051953bdbb832ced9ef26d1d3e6ea2ff21226 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlengine.cpp')
-rw-r--r--src/qml/qml/qqmlengine.cpp15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index d5a8371c7f..bd33650d9a 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -233,8 +233,19 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
d->outerContext->setContextObject(nullptr);
if (d->hasVMEMetaObject || d->hasInterceptorMetaObject) {
- p->metaObject->objectDestroyed(o);
- p->metaObject = nullptr;
+ // This is somewhat dangerous because another thread might concurrently
+ // try to resolve the dynamic metaobject. In practice this will then
+ // lead to either the code path that still returns the interceptor
+ // metaobject or the code path that returns the string casted one. Both
+ // is fine if you cannot actually touch the object itself. Since the
+ // other thread is obviously not synchronized to this one, it can't.
+ //
+ // In particular we do this when delivering the frameSwapped() signal
+ // in QQuickWindow. The handler for frameSwapped() is written in a way
+ // that is thread safe as long as QQuickWindow's dtor hasn't finished.
+ // QQuickWindow's dtor does synchronize with the render thread, but it
+ // runs _after_ qdeclarativeelement_destructor.
+ static_cast<QQmlInterceptorMetaObject *>(p->metaObject)->invalidate();
d->hasVMEMetaObject = d->hasInterceptorMetaObject = false;
}