[vlc-devel] [PATCH v2 02/14] qt: cancel preparse requests before destroying/changing model of NetworkMediaModel

Pierre Lamot pierre at videolabs.io
Fri Feb 7 14:00:12 CET 2020


  this caused a crash if the UI was destroyed when a request was pending
---
 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;
--
2.17.1


More information about the vlc-devel mailing list