[vlc-commits] qt: cancel preparse requests before destroying/changing model of NetworkMediaModel

Pierre Lamot git at videolan.org
Thu Feb 13 11:06:33 CET 2020


vlc | branch: master | Pierre Lamot <pierre at videolabs.io> | Thu Feb  6 09:52:39 2020 +0100| [2f1293d41241ca57de72944b417109df762f9aa8] | committer: Jean-Baptiste Kempf

qt: cancel preparse requests before destroying/changing model of NetworkMediaModel

  this caused a crash if the UI was destroyed when a request was pending

Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2f1293d41241ca57de72944b417109df762f9aa8
---

 modules/gui/qt/network/networkmediamodel.cpp | 18 +++++++++++++++++-
 modules/gui/qt/network/networkmediamodel.hpp |  5 ++++-
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/modules/gui/qt/network/networkmediamodel.cpp b/modules/gui/qt/network/networkmediamodel.cpp
index 1a24f3de91..ca1e94c51d 100644
--- a/modules/gui/qt/network/networkmediamodel.cpp
+++ b/modules/gui/qt/network/networkmediamodel.cpp
@@ -40,10 +40,23 @@ enum Role {
 
 NetworkMediaModel::NetworkMediaModel( QObject* parent )
     : QAbstractListModel( parent )
+    , m_preparseSem(1)
     , m_ml( nullptr )
 {
 }
 
+NetworkMediaModel::~NetworkMediaModel()
+{
+    //this can only be aquired from UI thread
+    if (!m_preparseSem.tryAcquire())
+    {
+        auto libvlc = vlc_object_instance(m_ctx->getIntf());
+        vlc_media_tree_PreparseCancel( libvlc, this );
+        //wait for the callback call on cancel
+        m_preparseSem.acquire();
+    }
+}
+
 QVariant NetworkMediaModel::data( const QModelIndex& index, int role ) const
 {
     if (!m_ctx)
@@ -255,6 +268,8 @@ bool NetworkMediaModel::initializeMediaSources()
         emit isIndexedChanged();
     }
 
+    vlc_media_tree_PreparseCancel( libvlc, this );
+    m_preparseSem.acquire();
     vlc_media_tree_Preparse( tree, libvlc, m_treeItem.media.get(), this );
     m_parsingPending = true;
     emit parsingPendingChanged(m_parsingPending);
@@ -335,8 +350,9 @@ void NetworkMediaModel::onItemRemoved(MediaSourcePtr, input_item_node_t * node,
     }, Qt::QueuedConnection);
 }
 
-void NetworkMediaModel::onItemPreparseEnded(MediaSourcePtr, input_item_node_t* node, enum input_item_preparse_status)
+void NetworkMediaModel::onItemPreparseEnded(MediaSourcePtr, input_item_node_t* node, enum input_item_preparse_status )
 {
+    m_preparseSem.release();
     InputItemPtr p_node { node->p_item };
     QMetaObject::invokeMethod(this, [this, p_node=std::move(p_node)]() {
         if (p_node != m_treeItem.media)
diff --git a/modules/gui/qt/network/networkmediamodel.hpp b/modules/gui/qt/network/networkmediamodel.hpp
index bc6c2ea8b5..969d085dc4 100644
--- a/modules/gui/qt/network/networkmediamodel.hpp
+++ b/modules/gui/qt/network/networkmediamodel.hpp
@@ -33,6 +33,8 @@
 #include <util/qml_main_context.hpp>
 #include "networksourcelistener.hpp"
 
+#include <QSemaphore>
+
 #include <memory>
 
 using MediaSourcePtr = vlc_shared_data_ptr_type(vlc_media_source_t,
@@ -98,6 +100,7 @@ public:
 
     explicit NetworkMediaModel(QObject* parent = nullptr);
     NetworkMediaModel( QmlMainContext* ctx, QString parentMrl, QObject* parent = nullptr );
+    virtual ~NetworkMediaModel() override;
 
     QVariant data(const QModelIndex& index, int role) const override;
     QHash<int, QByteArray> roleNames() const override;
@@ -171,7 +174,7 @@ private:
     bool m_indexed = false;
     bool m_canBeIndexed  = false;
     bool m_parsingPending = false;
-
+    QSemaphore m_preparseSem;
 
     std::vector<Item> m_items;
     QmlMainContext* m_ctx = nullptr;



More information about the vlc-commits mailing list