diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-03-09 09:53:30 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-03-09 10:54:39 +0100 |
commit | c2081016ecc894563f19d3e6bfdc7501aa23fe91 (patch) | |
tree | 6977e9c9a63c307a09c0dd6383db9fc4370bb351 /src | |
parent | f3dccc334f01d088fcdf1c2016c8153fe6154b61 (diff) |
Avoid unloading plugins which register types to prevent crashes
Plugins could register an arbitrary number of types in arbitrary places
with qRegisterMetaType. This would lead to crashes when the plugin is
unloaded, as the type registry would hold stale references to their
QMetaTypes. By not unloading the plugin, the metatypes are kept safe in
memory.
[ChangeLog][QML][Important Behavior Changes] When writing a
QQmlExtensionPlugin which procedurually registers types, you should
overload the newly introduced unregisterTypes function, if you want to
support unregistration with qmlClearEnginePlugins. Additionally, the
destructor of your plugin should not contain any logic.
Change-Id: I63b7a153f82be7996dbfca4d36f279c351dc6b9e
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/qtquick2/plugin.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlextensionplugin.cpp | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmlextensionplugin.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 14 |
4 files changed, 24 insertions, 4 deletions
diff --git a/src/imports/qtquick2/plugin.cpp b/src/imports/qtquick2/plugin.cpp index 4e14aff15e..dde0b7207a 100644 --- a/src/imports/qtquick2/plugin.cpp +++ b/src/imports/qtquick2/plugin.cpp @@ -64,10 +64,11 @@ public: QQmlQtQuick2Module::defineModule(); } - ~QtQuick2Plugin() override + void unregisterTypes() override { if (moduleDefined) QQmlQtQuick2Module::undefineModule(); + moduleDefined = false; } bool moduleDefined = false; diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp index 7a62c967e7..f779199b74 100644 --- a/src/qml/qml/qqmlextensionplugin.cpp +++ b/src/qml/qml/qqmlextensionplugin.cpp @@ -117,6 +117,16 @@ QUrl QQmlExtensionPlugin::baseUrl() const } /*! + \since 6.0 + + Override this method to unregister types manually registered in registerTypes. +*/ +void QQmlExtensionPlugin::unregisterTypes() +{ + +} + +/*! \internal */ diff --git a/src/qml/qml/qqmlextensionplugin.h b/src/qml/qml/qqmlextensionplugin.h index ef7ff422cd..78371106bd 100644 --- a/src/qml/qml/qqmlextensionplugin.h +++ b/src/qml/qml/qqmlextensionplugin.h @@ -64,6 +64,7 @@ public: QUrl baseUrl() const; void registerTypes(const char *uri) override = 0; + virtual void unregisterTypes(); void initializeEngine(QQmlEngine *engine, const char *uri) override; private: diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 076a23c1dd..47f7b40938 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -161,9 +161,17 @@ void qmlClearEnginePlugins() #if QT_CONFIG(library) for (auto &plugin : qAsConst(*plugins)) { QPluginLoader* loader = plugin.loader; - if (loader && !loader->unload()) - qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString())); - delete loader; + if (loader) { + auto extensionPlugin = qobject_cast<QQmlExtensionPlugin *>(loader->instance()); + if (extensionPlugin) { + extensionPlugin->unregisterTypes(); + } +#ifndef Q_OS_MACOS + if (!loader->unload()) + qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString())); + delete loader; +#endif + } } #endif plugins->clear(); |