Commit befb82c2 authored by Filip Roséen's avatar Filip Roséen Committed by Hugo Beauzée-Luyssen
Browse files

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's avatarHugo Beauzée-Luyssen <hugo@beauzee.fr>
parent cf59d2a3
......@@ -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 );
......
......@@ -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 );
......
......@@ -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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment