QFactoryLoader: also move staticplugin instances to the main thread

We already move the instances coming from dynamic plugins, but for some
reason we don't for the ones coming from staticplugins. There's no hint
about it in the history; my guess is it was simply forgotten when the
staticplugins were added.

This necessitated extending the mutex lock over the staticplugin list
scan so we'd reach the QObject::moveToThread() call too.

Change-Id: Ibe0107a9daf46792b09efffd9a7d9c45214aa589
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Thiago Macieira 2025-02-27 08:46:53 -03:00
parent a37606310e
commit 817fa23109
3 changed files with 17 additions and 16 deletions

View File

@ -39,13 +39,6 @@ QPermissionPlugin *permissionPlugin(const QPermission &permission)
qCDebug(lcPermissions) << "Found matching plugin" << qUtf8Printable(className);
auto *plugin = static_cast<QPermissionPlugin*>(pluginLoader()->instance(i));
if (!plugin->parent()) {
// We want to re-parent the plugin to the factory loader, so that it's
// cleaned up properly. To do so we first need to move the plugin to the
// same thread as the factory loader, as the plugin might be instantiated
// on a secondary thread if triggered from a checkPermission call (which
// is allowed on any thread).
plugin->moveToThread(pluginLoader->thread());
// Also, as setParent will involve sending a ChildAdded event to the parent,
// we need to make the call on the same thread as the parent lives, as events
// are not allowed to be sent to an object owned by another thread.

View File

@ -256,9 +256,9 @@ class QFactoryLoaderPrivate : public QObjectPrivate
public:
QFactoryLoaderPrivate() { }
QByteArray iid;
mutable QMutex mutex;
#if QT_CONFIG(library)
~QFactoryLoaderPrivate();
mutable QMutex mutex;
QDuplicateTracker<QString> loadedPaths;
std::vector<QLibraryPrivate::UniquePtr> libraries;
std::map<QString, QLibraryPrivate*> keyMap;
@ -558,20 +558,25 @@ QObject *QFactoryLoader::instance(int index) const
if (index < 0)
return nullptr;
#if QT_CONFIG(library)
QMutexLocker lock(&d->mutex);
QObject *obj = instanceHelper_locked(index);
if (obj && !obj->parent())
obj->moveToThread(QCoreApplicationPrivate::mainThread());
return obj;
}
inline QObject *QFactoryLoader::instanceHelper_locked(int index) const
{
Q_D(const QFactoryLoader);
#if QT_CONFIG(library)
if (size_t(index) < d->libraries.size()) {
QLibraryPrivate *library = d->libraries[index].get();
if (QObject *obj = library->pluginInstance()) {
if (!obj->parent())
obj->moveToThread(QCoreApplicationPrivate::mainThread());
return obj;
}
return nullptr;
return library->pluginInstance();
}
// we know d->libraries.size() <= index <= numeric_limits<decltype(index)>::max() → no overflow
index -= static_cast<int>(d->libraries.size());
lock.unlock();
#endif
QLatin1StringView iid(d->iid.constData(), d->iid.size());

View File

@ -62,6 +62,9 @@ public:
MetaDataList metaData() const;
QList<QCborArray> metaDataKeys() const;
QObject *instance(int index) const;
private:
inline QObject *instanceHelper_locked(int index) const;
};
template <class PluginInterface, class FactoryInterface, typename ...Args>