From 90d24b807373f7b4c10d1a88ffdb5d4ebed08de8 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Thu, 4 Jun 2020 10:33:47 +0200 Subject: 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 --- src/qml/jsapi/qjsengine_p.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/qml/jsapi') 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 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); } -- cgit v1.2.3