Fix crash with recursively loading cached compilation units
When a cached compilation unit depends on an import that is implemented as a Qml C++ plugin and that plugin in turn loads an asynchronous component that is cached, we would get a crash in the typeloader and a failing assertion (ASSERT: "d->m_mainThreadWaiting == false" in file qml/ftw/qqmlthread.cpp, line 300) This is because we did not implement the asynchronous loading within the loader thread for cached compilation units. This is simply done using a posted event, using the same mechanism used for other async load methods. Change-Id: Iefce67ab634ce26122c348dcdfc8e66b00fec671 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
74325015e7
commit
e59482f7f5
|
@ -148,6 +148,7 @@ public:
|
|||
void loadWithStaticData(QQmlDataBlob *b, const QByteArray &);
|
||||
void loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &);
|
||||
void loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit);
|
||||
void loadWithCachedUnitAsync(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit);
|
||||
void callCompleted(QQmlDataBlob *b);
|
||||
void callDownloadProgressChanged(QQmlDataBlob *b, qreal p);
|
||||
void initializeEngine(QQmlExtensionInterface *, const char *);
|
||||
|
@ -785,6 +786,12 @@ void QQmlDataLoaderThread::loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate
|
|||
callMethodInThread(&This::loadWithCachedUnitThread, b, unit);
|
||||
}
|
||||
|
||||
void QQmlDataLoaderThread::loadWithCachedUnitAsync(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
|
||||
{
|
||||
b->addref();
|
||||
postMethodToThread(&This::loadWithCachedUnitThread, b, unit);
|
||||
}
|
||||
|
||||
void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b)
|
||||
{
|
||||
b->addref();
|
||||
|
@ -979,7 +986,7 @@ void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &da
|
|||
}
|
||||
}
|
||||
|
||||
void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
|
||||
void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode)
|
||||
{
|
||||
#ifdef DATABLOB_DEBUG
|
||||
qWarning("QQmlDataLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()),
|
||||
|
@ -992,12 +999,18 @@ void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::C
|
|||
unlock();
|
||||
loadWithCachedUnitThread(blob, unit);
|
||||
lock();
|
||||
} else {
|
||||
} else if (mode == PreferSynchronous) {
|
||||
unlock();
|
||||
m_thread->loadWithCachedUnit(blob, unit);
|
||||
lock();
|
||||
if (!blob->isCompleteOrError())
|
||||
blob->m_data.setIsAsync(true);
|
||||
} else {
|
||||
Q_ASSERT(mode == Asynchronous);
|
||||
blob->m_data.setIsAsync(true);
|
||||
unlock();
|
||||
m_thread->loadWithCachedUnitAsync(blob, unit);
|
||||
lock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1601,7 +1614,7 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
|
|||
// TODO: if (compiledData == 0), is it safe to omit this insertion?
|
||||
m_typeCache.insert(url, typeData);
|
||||
if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
|
||||
QQmlDataLoader::loadWithCachedUnit(typeData, cachedUnit);
|
||||
QQmlDataLoader::loadWithCachedUnit(typeData, cachedUnit, mode);
|
||||
} else {
|
||||
QQmlDataLoader::load(typeData, mode);
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ public:
|
|||
|
||||
void load(QQmlDataBlob *, Mode = PreferSynchronous);
|
||||
void loadWithStaticData(QQmlDataBlob *, const QByteArray &, Mode = PreferSynchronous);
|
||||
void loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit);
|
||||
void loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode = PreferSynchronous);
|
||||
|
||||
QQmlEngine *engine() const;
|
||||
void initializeEngine(QQmlExtensionInterface *, const char *);
|
||||
|
|
Loading…
Reference in New Issue