vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Tue Jul 5 18:09:04 2011 +0300| [71adf301e50aef185ef903d542896071f78323ff] | committer: Rémi Denis-Courmont
VLM: use custom reference count instead of object destructor This should fix a crash whereby VLM is deleted before its child VOD server object. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=71adf301e50aef185ef903d542896071f78323ff --- src/input/vlm.c | 33 ++++++++++++++++++++------------- src/input/vlm_internal.h | 2 ++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/input/vlm.c b/src/input/vlm.c index 66dfbf7..ee7539d 100644 --- a/src/input/vlm.c +++ b/src/input/vlm.c @@ -51,6 +51,7 @@ #if defined (WIN32) && !defined (UNDER_CE) #include <sys/timeb.h> /* ftime() */ #endif +#include <limits.h> #include <vlc_input.h> #include <vlc_stream.h> @@ -66,7 +67,6 @@ * Local prototypes. *****************************************************************************/ -static void vlm_Destructor( vlm_t *p_vlm ); static void* Manage( void * ); static int vlm_MediaVodControl( void *, vod_media_t *, const char *, int, va_list ); @@ -139,7 +139,10 @@ vlm_t *vlm_New ( vlc_object_t *p_this ) p_vlm = *pp_vlm; if( p_vlm ) { /* VLM already exists */ - vlc_object_hold( p_vlm ); + if( likely( p_vlm->users < UINT_MAX ) ) + p_vlm->users++; + else + p_vlm = NULL; vlc_mutex_unlock( &vlm_mutex ); return p_vlm; } @@ -157,6 +160,7 @@ vlm_t *vlm_New ( vlc_object_t *p_this ) vlc_mutex_init( &p_vlm->lock ); vlc_mutex_init( &p_vlm->lock_manage ); vlc_cond_init_daytime( &p_vlm->wait_manage ); + p_vlm->users = 1; p_vlm->input_state_changed = false; p_vlm->i_id = 1; TAB_INIT( p_vlm->i_media, p_vlm->media ); @@ -196,7 +200,6 @@ vlm_t *vlm_New ( vlc_object_t *p_this ) } free( psz_vlmconf ); - vlc_object_set_destructor( p_vlm, (vlc_destructor_t)vlm_Destructor ); vlc_mutex_unlock( &vlm_mutex ); return p_vlm; @@ -208,18 +211,22 @@ vlm_t *vlm_New ( vlc_object_t *p_this ) void vlm_Delete( vlm_t *p_vlm ) { /* vlm_Delete() is serialized against itself, and against vlm_New(). - * This way, vlm_Destructor () (called from vlc_objet_release() above) - * is serialized against setting libvlc_priv->p_vlm from vlm_New(). */ + * This mutex protects libvlc_priv->p_vlm and p_vlm->users. */ vlc_mutex_lock( &vlm_mutex ); - vlc_object_release( p_vlm ); + assert( p_vlm->users > 0 ); + if( --p_vlm->users == 0 ) + { + assert( libvlc_priv(p_vlm->p_libvlc)->p_vlm = p_vlm ); + libvlc_priv(p_vlm->p_libvlc)->p_vlm = NULL; + } + else + p_vlm = NULL; vlc_mutex_unlock( &vlm_mutex ); -} -/***************************************************************************** - * vlm_Destructor: - *****************************************************************************/ -static void vlm_Destructor( vlm_t *p_vlm ) -{ + if( p_vlm == NULL ) + return; + + /* Destroy and release VLM */ vlc_mutex_lock( &p_vlm->lock ); vlm_ControlInternal( p_vlm, VLM_CLEAR_MEDIAS ); TAB_CLEAN( p_vlm->i_media, p_vlm->media ); @@ -228,7 +235,6 @@ static void vlm_Destructor( vlm_t *p_vlm ) TAB_CLEAN( p_vlm->i_schedule, p_vlm->schedule ); vlc_mutex_unlock( &p_vlm->lock ); - libvlc_priv(p_vlm->p_libvlc)->p_vlm = NULL; vlc_object_kill( p_vlm ); if( p_vlm->p_vod ) @@ -248,6 +254,7 @@ static void vlm_Destructor( vlm_t *p_vlm ) vlc_cond_destroy( &p_vlm->wait_manage ); vlc_mutex_destroy( &p_vlm->lock ); vlc_mutex_destroy( &p_vlm->lock_manage ); + vlc_object_release( p_vlm ); } /***************************************************************************** diff --git a/src/input/vlm_internal.h b/src/input/vlm_internal.h index 0ecfd37..875d50c 100644 --- a/src/input/vlm_internal.h +++ b/src/input/vlm_internal.h @@ -89,6 +89,8 @@ struct vlm_t vlc_thread_t thread; vlc_mutex_t lock_manage; vlc_cond_t wait_manage; + unsigned users; + /* tell vlm thread there is work to do */ bool input_state_changed; /* */ _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
