[vlc-commits] playlist: fix deadlock on destruction while preparser adds items to playlist

Filip Roséen git at videolan.org
Wed Mar 29 17:37:09 CEST 2017


vlc | branch: master | Filip Roséen <filip at atch.se> | Wed Mar 22 15:57:25 2017 +0100| [befb82c28d2b56716c2d69e3e9fcdd5d1c2fa514] | committer: Hugo Beauzée-Luyssen

playlist: fix deadlock on destruction while preparser adds items to playlist

As we can have incoming requests to the preparser while we are
destroying libvlc, we can end up in a deadlock while we are removing
all playlist_item_t from the playlist, while an item being preparsed
tries to add additional items to the list.

These changes fixes the issue by introducing a preparser-deactivation
function, that will make sure that we:

 1) clear out any pending preparsing requests
 2) cancel the current item preparsing (blocking)
 3) prevent further requests to the preparser

fixes: #18151

Signed-off-by: Hugo Beauzée-Luyssen <hugo at beauzee.fr>

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

 src/libvlc.c             |  3 +++
 src/playlist/preparser.c | 11 +++++++++++
 src/playlist/preparser.h |  8 ++++++++
 3 files changed, 22 insertions(+)

diff --git a/src/libvlc.c b/src/libvlc.c
index 34f24ba..4b220d2 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -507,6 +507,9 @@ void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
 {
     libvlc_priv_t *priv = libvlc_priv (p_libvlc);
 
+    if (priv->parser != NULL)
+        playlist_preparser_Deactivate(priv->parser);
+
     /* Ask the interfaces to stop and destroy them */
     msg_Dbg( p_libvlc, "removing all interfaces" );
     intf_DestroyAll( p_libvlc );
diff --git a/src/playlist/preparser.c b/src/playlist/preparser.c
index c6cdab2..d7e2d8c 100644
--- a/src/playlist/preparser.c
+++ b/src/playlist/preparser.c
@@ -36,6 +36,7 @@ struct playlist_preparser_t
     vlc_object_t* owner;
     playlist_fetcher_t* fetcher;
     struct background_worker* worker;
+    atomic_bool deactivated;
 };
 
 static int InputEvent( vlc_object_t* obj, const char* varname,
@@ -127,6 +128,7 @@ playlist_preparser_t* playlist_preparser_New( vlc_object_t *parent )
 
     preparser->owner = parent;
     preparser->fetcher = playlist_fetcher_New( parent );
+    atomic_init( &preparser->deactivated, false );
 
     if( unlikely( !preparser->fetcher ) )
         msg_Warn( parent, "unable to create art fetcher" );
@@ -138,6 +140,9 @@ void playlist_preparser_Push( playlist_preparser_t *preparser,
     input_item_t *item, input_item_meta_request_option_t i_options,
     int timeout, void *id )
 {
+    if( atomic_load( &preparser->deactivated ) )
+        return;
+
     vlc_mutex_lock( &item->lock );
     int i_type = item->i_type;
     int b_net = item->b_net;
@@ -172,6 +177,12 @@ void playlist_preparser_Cancel( playlist_preparser_t *preparser, void *id )
     background_worker_Cancel( preparser->worker, id );
 }
 
+void playlist_preparser_Deactivate( playlist_preparser_t* preparser )
+{
+    atomic_store( &preparser->deactivated, true );
+    background_worker_Cancel( preparser->worker, NULL );
+}
+
 void playlist_preparser_Delete( playlist_preparser_t *preparser )
 {
     background_worker_Delete( preparser->worker );
diff --git a/src/playlist/preparser.h b/src/playlist/preparser.h
index d1cd69e..48862bd 100644
--- a/src/playlist/preparser.h
+++ b/src/playlist/preparser.h
@@ -75,5 +75,13 @@ void playlist_preparser_Cancel( playlist_preparser_t *, void *id );
  */
 void playlist_preparser_Delete( playlist_preparser_t * );
 
+/**
+ * This function deactivates the preparser
+ *
+ * All pending requests will be removed, and it will block until the currently
+ * running entity has finished (if any).
+ */
+void playlist_preparser_Deactivate( playlist_preparser_t * );
+
 #endif
 



More information about the vlc-commits mailing list