aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsapi
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-06-04 10:33:47 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2020-06-05 13:02:29 +0200
commit90d24b807373f7b4c10d1a88ffdb5d4ebed08de8 (patch)
tree8487cc2f11489a421ae26c8c632d4b6e20dcf5f1 /src/qml/jsapi
parent3d1b34e5bfd56d8035fa53ffb14726e6120f3ff0 (diff)
Fix race condition in QQmlData::createPropertyCache
As noted in QJSEnginePrivate::cache, there can be a race between calling addRef on the QQmlPropertyCache and another thread derefing and consequently deleting it. To avoid this, we introduce a doRef flag in QQmlMetaTypeData::propertyCache, which tells it to ref the the cache. This fixes the issue, as the QQmlMetaTypeDataPtr in propertyCache() acts as a mutex. Fixes: QTBUG-84692 Pick-to: 5.15 Change-Id: I962d28cfd22696aad89a660e41c55f63a8791b44 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/jsapi')
-rw-r--r--src/qml/jsapi/qjsengine_p.h12
1 files changed, 6 insertions, 6 deletions
diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h
index 0aff6595b6..fb88781852 100644
--- a/src/qml/jsapi/qjsengine_p.h
+++ b/src/qml/jsapi/qjsengine_p.h
@@ -111,8 +111,8 @@ public:
QProperty<QString> uiLanguage;
// These methods may be called from the QML loader thread
- inline QQmlPropertyCache *cache(QObject *obj, QTypeRevision version = QTypeRevision());
- inline QQmlPropertyCache *cache(const QMetaObject *obj, QTypeRevision version = QTypeRevision());
+ inline QQmlPropertyCache *cache(QObject *obj, QTypeRevision version = QTypeRevision(), bool doRef = false);
+ inline QQmlPropertyCache *cache(const QMetaObject *obj, QTypeRevision version = QTypeRevision(), bool doRef = false);
};
QJSEnginePrivate::Locker::Locker(const QJSEngine *e)
@@ -162,14 +162,14 @@ and deleted before the loader thread has a chance to use or reference it. This
can't currently happen as the cache holds a reference to the
QQmlPropertyCache until the QQmlEngine is destroyed.
*/
-QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, QTypeRevision version)
+QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, QTypeRevision version, bool doRef)
{
if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
return nullptr;
Locker locker(this);
const QMetaObject *mo = obj->metaObject();
- return QQmlMetaType::propertyCache(mo, version);
+ return QQmlMetaType::propertyCache(mo, version, doRef);
}
/*!
@@ -181,12 +181,12 @@ exist for the lifetime of the QQmlEngine.
The returned cache is not referenced, so if it is to be stored, call addref().
*/
-QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, QTypeRevision version)
+QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, QTypeRevision version, bool doRef)
{
Q_ASSERT(metaObject);
Locker locker(this);
- return QQmlMetaType::propertyCache(metaObject, version);
+ return QQmlMetaType::propertyCache(metaObject, version, doRef);
}