Commit 80684e78 authored by Laurent Aimar's avatar Laurent Aimar

Fixed a race condition with input creation and events.

input_CreateThread* have been splitted in two functions:
 - input_Create
 - input_Start
to allow attaching to input events and creating settings/variables
before starting the input thread.

For consistency, input_StopThread has been renamed input_Stop.

Initial report from Hugo Beauzee-Luyssen.
parent a135b02f
......@@ -248,14 +248,16 @@ static inline void vlc_input_attachment_Delete( input_attachment_t *a )
#define INPUT_UPDATE_META 0x0040
#define INPUT_UPDATE_SIGNAL 0x0080
/** Get the input item for an input thread
* FIXME see src/input/item.c but is is unsafe unless
* you hold p_input
/**
* This defines private core storage for an input.
*/
VLC_EXPORT(input_item_t*, input_GetItem, (input_thread_t*));
typedef struct input_thread_private_t input_thread_private_t;
/**
* This defines an opaque input resource handler.
*/
typedef struct input_resource_t input_resource_t;
/**
* Main structure representing an input thread. This structure is mostly
* private. The only public fields are READ-ONLY. You must use the helpers
......@@ -431,32 +433,9 @@ typedef enum input_event_type_e
} input_event_type_e;
/** @}*/
/*****************************************************************************
* Prototypes
*****************************************************************************/
/**
* It will create a new input thread.
*
* You must call input_StopThread() on it and then vlc_object_release().
* Input queries
*/
#define input_CreateThread(a,b) __input_CreateThread(VLC_OBJECT(a),b)
VLC_EXPORT( input_thread_t *, __input_CreateThread, ( vlc_object_t *, input_item_t * ) );
/**
* It will ask a input_thread_t to stop.
*
* b_abort must be true when a user stop is requested and not because you have
* detected an error or an eof. It will be used to properly send the
* INPUT_EVENT_ABORT event.
*/
VLC_EXPORT( void, input_StopThread, ( input_thread_t *, bool b_abort ) );
#define input_Read(a,b,c) __input_Read(VLC_OBJECT(a),b, c)
VLC_EXPORT( int, __input_Read, ( vlc_object_t *, input_item_t *, bool ) );
enum input_query_e
{
/* input variable "position" */
......@@ -526,9 +505,37 @@ enum input_query_e
INPUT_GET_VOUTS, /* arg1=vout_thread_t ***, int * res=can fail */
};
/** @}*/
/*****************************************************************************
* Prototypes
*****************************************************************************/
#define input_Create(a,b,c,d) __input_Create(VLC_OBJECT(a),b,c,d)
VLC_EXPORT( input_thread_t *, __input_Create, ( vlc_object_t *p_parent, input_item_t *, const char *psz_log, input_resource_t * ) );
#define input_CreateAndStart(a,b,c) __input_CreateAndStart(VLC_OBJECT(a),b,c)
VLC_EXPORT( input_thread_t *, __input_CreateAndStart, ( vlc_object_t *p_parent, input_item_t *, const char *psz_log ) );
VLC_EXPORT( int, input_Start, ( input_thread_t * ) );
VLC_EXPORT( void, input_Stop, ( input_thread_t *, bool b_abort ) );
#define input_Read(a,b,c) __input_Read(VLC_OBJECT(a),b, c)
VLC_EXPORT( int, __input_Read, ( vlc_object_t *, input_item_t *, bool ) );
VLC_EXPORT( int, input_vaControl,( input_thread_t *, int i_query, va_list ) );
VLC_EXPORT( int, input_Control, ( input_thread_t *, int i_query, ... ) );
/**
* Get the input item for an input thread
*
* You have to keep a reference to the input or to the input_item_t until
* you do not need it anymore.
*/
VLC_EXPORT( input_item_t*, input_GetItem, ( input_thread_t * ) );
/**
* It will return the current state of the input.
* Provided for convenience.
......@@ -567,7 +574,7 @@ static inline vout_thread_t *input_GetVout( input_thread_t *p_input )
vlc_object_release( (vlc_object_t *)(pp_vout[i]) );
p_vout = (i_vout >= 1) ? pp_vout[0] : NULL;
free (pp_vout);
free( pp_vout );
return p_vout;
}
......
......@@ -159,13 +159,16 @@ static void Close( vlc_object_t *p_this )
for( i = 0; i < p_sys->i_input; i++ )
{
if( p_sd->p_sys->pp_input[i] )
{
input_StopThread( p_sd->p_sys->pp_input[i], true );
vlc_object_release( p_sd->p_sys->pp_input[i] );
input_thread_t *p_input = p_sd->p_sys->pp_input[i];
if( !p_input )
continue;
input_Stop( p_input, true );
vlc_thread_join( p_input );
vlc_object_release( p_input );
p_sd->p_sys->pp_input[i] = NULL;
}
}
free( p_sd->p_sys->pp_input );
for( i = 0; i < p_sys->i_urls; i++ ) free( p_sys->ppsz_urls[i] );
free( p_sys->ppsz_urls );
......@@ -197,11 +200,14 @@ static void *Run( void *data )
for( int i = 0; i < p_sd->p_sys->i_input; i++ )
{
if( p_sd->p_sys->pp_input[i]->b_eof
|| p_sd->p_sys->pp_input[i]->b_error )
input_thread_t *p_input = p_sd->p_sys->pp_input[i];
if( p_input->b_eof || p_input->b_error )
{
input_StopThread( p_sd->p_sys->pp_input[i], false );
vlc_object_release( p_sd->p_sys->pp_input[i] );
input_Stop( p_input, false );
vlc_thread_join( p_input );
vlc_object_release( p_input );
p_sd->p_sys->pp_input[i] = NULL;
REMOVE_ELEM( p_sys->pp_input, p_sys->i_input, i );
i--;
......@@ -253,7 +259,7 @@ static void ParseUrls( services_discovery_t *p_sd, char *psz_urls )
services_discovery_AddItem( p_sd, p_input, NULL /* no cat */ );
vlc_gc_decref( p_input );
INSERT_ELEM( p_sys->pp_input, p_sys->i_input, p_sys->i_input,
input_CreateThread( p_sd, p_input ) );
input_CreateAndStart( p_sd, p_input, NULL ) );
}
if( psz_tok ) psz_urls = psz_tok+1;
else return;
......
......@@ -89,7 +89,7 @@ static void release_input_thread( libvlc_media_player_t *p_mi, bool b_input_abor
input_event_changed, p_mi );
/* We owned this one */
input_StopThread( p_input_thread, b_input_abort );
input_Stop( p_input_thread, b_input_abort );
vlc_thread_join( p_input_thread );
var_Destroy( p_input_thread, "drawable-hwnd" );
......@@ -606,8 +606,8 @@ void libvlc_media_player_play( libvlc_media_player_t *p_mi,
return;
}
p_mi->p_input_thread = input_CreateThread(
p_mi->p_libvlc_instance->p_libvlc_int, p_mi->p_md->p_input_item );
p_mi->p_input_thread = input_Create( p_mi->p_libvlc_instance->p_libvlc_int,
p_mi->p_md->p_input_item, NULL, NULL );
if( !p_mi->p_input_thread )
{
......@@ -643,6 +643,12 @@ void libvlc_media_player_play( libvlc_media_player_t *p_mi,
var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
if( input_Start( p_input_thread ) )
{
vlc_object_release( p_input_thread );
p_mi->p_input_thread = NULL;
}
vlc_mutex_unlock( &p_mi->object_lock );
}
......@@ -717,7 +723,7 @@ void libvlc_media_player_stop( libvlc_media_player_t *p_mi,
if( !p_input_thread )
return;
input_StopThread( p_input_thread, true );
input_Stop( p_input_thread, true );
vlc_object_release( p_input_thread );
p_mi->p_input_thread = NULL;
}
......
This diff is collapsed.
......@@ -46,11 +46,6 @@ int input_Preparse( vlc_object_t *, input_item_t * );
* FIXME it should NOT be defined here or not coded in misc/stats.c */
input_stats_t *stats_NewInputStats( input_thread_t *p_input );
/**
* This defines an opaque input resource handler.
*/
typedef struct input_resource_t input_resource_t;
/**
* This function releases an input_resource_t and all associated resources.
*/
......@@ -74,8 +69,6 @@ void input_resource_TerminateVout( input_resource_t *p_resource );
bool input_resource_HasVout( input_resource_t *p_resource );
/* input.c */
#define input_CreateThreadExtended(a,b,c,d) __input_CreateThreadExtended(VLC_OBJECT(a),b,c,d)
input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, input_resource_t * );
/**
* This function detaches resources from a dead input.
......
......@@ -531,12 +531,12 @@ static int vlm_OnMediaUpdate( vlm_t *p_vlm, vlm_media_sys_t *p_media )
if( asprintf( &psz_header, _("Media: %s"), p_cfg->psz_name ) == -1 )
psz_header = NULL;
if( (p_input = input_CreateThreadExtended( p_vlm->p_libvlc, p_media->vod.p_item, psz_header, NULL ) ) )
if( (p_input = input_CreateAndStart( p_vlm->p_libvlc, p_media->vod.p_item, psz_header ) ) )
{
while( !p_input->b_eof && !p_input->b_error )
msleep( 100000 );
input_StopThread( p_input, false );
input_Stop( p_input, false );
vlc_thread_join( p_input );
vlc_object_release( p_input );
}
......@@ -778,7 +778,7 @@ static void vlm_MediaInstanceDelete( vlm_t *p_vlm, int64_t id, vlm_media_instanc
{
input_resource_t *p_resource;
input_StopThread( p_input, true );
input_Stop( p_input, true );
vlc_thread_join( p_input );
p_resource = input_DetachResource( p_input );
......@@ -861,7 +861,7 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
return VLC_SUCCESS;
}
input_StopThread( p_input, !p_input->b_eof && !p_input->b_error );
input_Stop( p_input, !p_input->b_eof && !p_input->b_error );
vlc_thread_join( p_input );
p_instance->p_input_resource = input_DetachResource( p_input );
......@@ -881,8 +881,13 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
if( asprintf( &psz_log, _("Media: %s"), p_media->cfg.psz_name ) != -1 )
{
p_instance->p_input = input_CreateThreadExtended( p_vlm->p_libvlc, p_instance->p_item,
p_instance->p_input = input_Create( p_vlm->p_libvlc, p_instance->p_item,
psz_log, p_instance->p_input_resource );
if( p_instance->p_input && input_Start( p_instance->p_input ) )
{
vlc_object_release( p_instance->p_input );
p_instance->p_input = NULL;
}
p_instance->p_input_resource = NULL;
if( !p_instance->p_input )
......
......@@ -169,8 +169,9 @@ image_Mime2Fourcc
image_Type2Fourcc
InitMD5
input_Control
__input_Create
__input_CreateAndStart
input_CreateFilename
__input_CreateThread
input_DecoderDecode
input_DecoderDelete
input_DecoderNew
......@@ -199,7 +200,8 @@ input_item_SetURI
input_MetaTypeToLocalizedString
__input_Read
input_SplitMRL
input_StopThread
input_Start
input_Stop
input_vaControl
__intf_Create
__intf_Eject
......
......@@ -823,7 +823,7 @@ static void GoAndPreparse( playlist_t *p_playlist, int i_mode,
pl_priv(p_playlist)->request.i_skip = 0;
pl_priv(p_playlist)->request.p_item = p_toplay;
if( pl_priv(p_playlist)->p_input )
input_StopThread( pl_priv(p_playlist)->p_input, true );
input_Stop( pl_priv(p_playlist)->p_input, true );
pl_priv(p_playlist)->request.i_status = PLAYLIST_RUNNING;
vlc_cond_signal( &pl_priv(p_playlist)->signal );
}
......
......@@ -251,14 +251,17 @@ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item )
assert( p_sys->p_input == NULL );
input_thread_t *p_input_thread =
input_CreateThreadExtended( p_playlist, p_input, NULL, p_sys->p_input_resource );
input_thread_t *p_input_thread = input_Create( p_playlist, p_input, NULL, p_sys->p_input_resource );
if( p_input_thread )
{
p_sys->p_input = p_input_thread;
var_AddCallback( p_input_thread, "intf-event", InputEvent, p_playlist );
if( input_Start( p_sys->p_input ) )
{
vlc_object_release( p_input_thread );
p_sys->p_input = p_input_thread = NULL;
}
}
p_sys->p_input_resource = NULL;
......@@ -473,7 +476,7 @@ static int LoopInput( playlist_t *p_playlist )
if( ( p_sys->request.b_request || !vlc_object_alive( p_playlist ) ) && !p_input->b_die )
{
PL_DEBUG( "incoming request - stopping current input" );
input_StopThread( p_input, true );
input_Stop( p_input, true );
}
/* This input is dead. Remove it ! */
......@@ -514,7 +517,7 @@ static int LoopInput( playlist_t *p_playlist )
else if( p_input->b_error || p_input->b_eof )
{
PL_DEBUG( "finished input" );
input_StopThread( p_input, false );
input_Stop( p_input, false );
}
return VLC_SUCCESS;
}
......
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