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

Pierre Lamot pierre at videolabs.io
Thu Feb 6 13:56:39 CET 2020


  this caused a crash if the UI was destroyed when a request was pending
---
 modules/gui/qt/network/networkmediamodel.cpp | 23 +++++++++++++++++++-
 modules/gui/qt/network/networkmediamodel.hpp |  5 ++++-
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/modules/gui/qt/network/networkmediamodel.cpp b/modules/gui/qt/network/networkmediamodel.cpp
index 1a24f3de91..dca7534438 100644
--- a/modules/gui/qt/network/networkmediamodel.cpp
+++ b/modules/gui/qt/network/networkmediamodel.cpp
@@ -40,10 +40,22 @@ enum Role {
 
 NetworkMediaModel::NetworkMediaModel( QObject* parent )
     : QAbstractListModel( parent )
+    , m_preparseSem(1)
     , m_ml( nullptr )
 {
 }
 
+NetworkMediaModel::~NetworkMediaModel()
+{
+    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 +267,11 @@ bool NetworkMediaModel::initializeMediaSources()
         emit isIndexedChanged();
     }
 
+    if (!m_preparseSem.tryAcquire())
+    {
+        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 +352,12 @@ 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 status)
 {
+    m_preparseSem.release();
+    if (status != ITEM_PREPARSE_DONE)
+        return;
+
     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