[vlc-commits] [Git][videolan/vlc][master] 5 commits: qt: fix GetMediaSource returning null models in DeviceSourceProvider

Steve Lhomme (@robUx4) gitlab at videolan.org
Fri Dec 20 10:09:02 UTC 2024



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
6a6da651 by Pierre Lamot at 2024-12-20T09:47:11+00:00
qt: fix GetMediaSource returning null models in DeviceSourceProvider

fix: #28907

- - - - -
5bc89f66 by Pierre Lamot at 2024-12-20T09:47:11+00:00
qt: don't append source name to model name if source is discarded in DeviceSourceProvider

- - - - -
3143296b by Pierre Lamot at 2024-12-20T09:47:11+00:00
qt: fix wrong callback called on MediaSourceModel::mediaRemoved

- - - - -
a5cca93e by Pierre Lamot at 2024-12-20T09:47:11+00:00
qt: fix unique connection can't be used with lambdas in NetworkDeviceModel

We need to use the lamdda to be able to retreive the shared pointer on the
caller, using the QObject::sender isn't enough to retrieve it. To ensure that
the connection is unique, we store the corresponding connection for the
(unlikely) case where the model would be re-initialized

- - - - -
f2379a0e by Pierre Lamot at 2024-12-20T09:47:11+00:00
qt: fix MediaSourceModel leak in DeviceSourceProvider

Storing a shared pointer in the connection may leak the object as
the connection is destroyed when the source is destroyed, but the
connection holds a reference. Instead, we store a weak pointer, the value will
remains valid as the connection has the same lifespan as the sender.

- - - - -


2 changed files:

- modules/gui/qt/network/devicesourceprovider.cpp
- modules/gui/qt/network/networkdevicemodel.cpp


Changes:

=====================================
modules/gui/qt/network/devicesourceprovider.cpp
=====================================
@@ -105,6 +105,8 @@ MediaSourceModel::~MediaSourceModel()
 
 void MediaSourceModel::init()
 {
+    assert(m_mediaSource);
+
     if (m_listenner)
         return;
 
@@ -196,6 +198,9 @@ SharedMediaSourceModel MediaSourceCache::getMediaSourceModel(vlc_media_source_pr
         vlc_media_source_provider_GetMediaSource(provider, name),
         false );
 
+    if (!mediaSource)
+        return nullptr;
+
     SharedMediaSourceModel item = SharedMediaSourceModel::create(mediaSource);
     m_cache[key] = item;
     return item;
@@ -254,15 +259,15 @@ void DeviceSourceProvider::init()
                 if ( nameFilter != '*' && nameFilter != sourceName )
                     continue;
 
-                ctx.name += ctx.name.isEmpty() ? qfu( meta->longname ) : ", " + qfu( meta->longname );
-
                 SharedMediaSourceModel mediaSource = MediaSourceCache::getInstance()->getMediaSourceModel(provider, meta->name);
-                //ensure this QObject don't live in the worker thread
-                mediaSource->moveToThread(thread);
 
                 if (!mediaSource)
                     continue;
 
+                //ensure this QObject don't live in the worker thread
+                mediaSource->moveToThread(thread);
+
+                ctx.name += ctx.name.isEmpty() ? qfu( meta->longname ) : ", " + qfu( meta->longname );
                 ctx.sources.push_back(mediaSource);
             }
         },


=====================================
modules/gui/qt/network/networkdevicemodel.cpp
=====================================
@@ -260,6 +260,10 @@ public:
             emit q->nameChanged();
         });
 
+        for (auto conn : m_sourceUpdateConnections)
+            QObject::disconnect(conn);
+        m_sourceUpdateConnections.clear();
+
         //itemsUpdated is called only once after init.
         QObject::connect(m_sourcesProvider.get(), &DeviceSourceProvider::itemsUpdated, q,
                 [this]()
@@ -270,16 +274,30 @@ public:
                 for (const SharedInputItem& media : source->getMedias())
                     onMediaAdded(source, media);
 
-                QObject::connect(
+                //don't store a strong reference in the lambda or this may leak the source
+                //as the connection is destroyed when the source is destroyed but the
+                //connection holds a reference
+                QWeakPointer<MediaSourceModel> weakSource{source};
+
+                auto conn = QObject::connect(
                     source.get(), &MediaSourceModel::mediaAdded,
-                    q_ptr, [this, source](SharedInputItem media) {
-                        onMediaAdded(source, media);
-                    }, Qt::UniqueConnection);
-                QObject::connect(
+                    q_ptr, [this, weakSource](SharedInputItem media) {
+                        //source is the signal emitter, it should always exist
+                        auto strongSource  = weakSource.toStrongRef();
+                        assert(strongSource);
+                        onMediaAdded(strongSource, media);
+                    });
+                m_sourceUpdateConnections.push_back(conn);
+
+                conn = QObject::connect(
                     source.get(), &MediaSourceModel::mediaRemoved,
-                    q_ptr, [this, source](SharedInputItem media) {
-                        onMediaAdded(source, media);
-                    }, Qt::UniqueConnection);
+                    q_ptr, [this, weakSource](SharedInputItem media) {
+                        auto strongSource  = weakSource.toStrongRef();
+                        assert(strongSource);
+                        onMediaRemoved(strongSource, media);
+                    });
+
+                m_sourceUpdateConnections.push_back(conn);
             }
 
             m_revision += 1;
@@ -374,6 +392,8 @@ public:
     NetworkDeviceModel::SDCatType m_sdSource = NetworkDeviceModel::CAT_UNDEFINED;
     QString m_sourceName; // '*' -> all sources
     QString m_name; // source long name
+
+    std::vector<QMetaObject::Connection> m_sourceUpdateConnections;
 };
 
 NetworkDeviceModel::NetworkDeviceModel( QObject* parent )



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/ba595bce6ce184ab2680dd185e5a6ccaf309ba2e...f2379a0e276597efdfe7a6aa970fb0f9ae21fbc3

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/ba595bce6ce184ab2680dd185e5a6ccaf309ba2e...f2379a0e276597efdfe7a6aa970fb0f9ae21fbc3
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list