[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