vlc | branch: master | Filip Roséen <[email protected]> | 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 <[email protected]> > 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 _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
