X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fobjects.c;h=d4a808c61d03873a070611b4d89db2f0a2407ef1;hb=78418c511a5eb18e5bf1f3e552676a40e6d8d15f;hp=7d5570fa0f33b2959aa496222f71219692dbb988;hpb=97676090ce41fef305459c6082651cbdd061452d;p=vlc diff --git a/src/misc/objects.c b/src/misc/objects.c index 7d5570fa0f..d4a808c61d 100644 --- a/src/misc/objects.c +++ b/src/misc/objects.c @@ -67,6 +67,10 @@ #if defined (HAVE_SYS_EVENTFD_H) # include +# ifndef EFD_CLOEXEC +# define EFD_CLOEXEC 0 +# warning EFD_CLOEXEC missing. Consider updating libc. +# endif #endif @@ -101,8 +105,9 @@ static void libvlc_unlock (libvlc_int_t *p_libvlc) vlc_mutex_unlock (&(libvlc_priv (p_libvlc)->structure_lock)); } -void *__vlc_custom_create( vlc_object_t *p_this, size_t i_size, - int i_type, const char *psz_type ) +#undef vlc_custom_create +void *vlc_custom_create( vlc_object_t *p_this, size_t i_size, + int i_type, const char *psz_type ) { vlc_object_t *p_new; vlc_object_internals_t *p_priv; @@ -154,6 +159,9 @@ void *__vlc_custom_create( vlc_object_t *p_this, size_t i_size, p_priv->b_thread = false; p_new->p_parent = NULL; p_priv->first = NULL; +#ifndef NDEBUG + p_priv->old_parent = NULL; +#endif /* Initialize mutexes and condvars */ vlc_mutex_init( &p_priv->var_lock ); @@ -186,7 +194,7 @@ void *vlc_object_create( vlc_object_t *p_this, size_t i_size ) return vlc_custom_create( p_this, i_size, VLC_OBJECT_GENERIC, "generic" ); } - +#undef vlc_object_set_destructor /** **************************************************************************** * Set the destructor of a vlc object @@ -195,8 +203,8 @@ void *vlc_object_create( vlc_object_t *p_this, size_t i_size ) * when the object is destroyed when the its refcount reaches 0. * (It is called by the internal function vlc_object_destroy()) *****************************************************************************/ -void __vlc_object_set_destructor( vlc_object_t *p_this, - vlc_destructor_t pf_destructor ) +void vlc_object_set_destructor( vlc_object_t *p_this, + vlc_destructor_t pf_destructor ) { vlc_object_internals_t *p_priv = vlc_internals(p_this ); @@ -352,8 +360,11 @@ int vlc_object_waitpipe( vlc_object_t *obj ) /* This can only ever happen if someone killed us without locking: */ assert (internals->pipes[1] == -1); + /* pipe() is not a cancellation point, but write() is and eventfd() is + * unspecified (not in POSIX). */ + int canc = vlc_savecancel (); #if defined (HAVE_SYS_EVENTFD_H) - internals->pipes[0] = internals->pipes[1] = eventfd (0, 0); + internals->pipes[0] = internals->pipes[1] = eventfd (0, EFD_CLOEXEC); if (internals->pipes[0] == -1) #endif { @@ -366,17 +377,18 @@ int vlc_object_waitpipe( vlc_object_t *obj ) msg_Dbg (obj, "waitpipe: object already dying"); write (internals->pipes[1], &(uint64_t){ 1 }, sizeof (uint64_t)); } + vlc_restorecancel (canc); } vlc_mutex_unlock (&pipe_lock); return internals->pipes[0]; } - +#undef vlc_object_kill /** * Requests termination of an object, cancels the object thread, and make the * object wait pipe (if it exists) readable. Not a cancellation point. */ -void __vlc_object_kill( vlc_object_t *p_this ) +void vlc_object_kill( vlc_object_t *p_this ) { vlc_object_internals_t *priv = vlc_internals( p_this ); int fd = -1; @@ -403,14 +415,14 @@ void __vlc_object_kill( vlc_object_t *p_this ) } } - +#undef vlc_object_find /***************************************************************************** * find a typed object and increment its refcount ***************************************************************************** * This function recursively looks for a given object type. i_mode can be one * of FIND_PARENT, FIND_CHILD or FIND_ANYWHERE. *****************************************************************************/ -void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode ) +void * vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode ) { vlc_object_t *p_found; @@ -423,7 +435,7 @@ void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode ) /* Otherwise, recursively look for the object */ if (i_mode == FIND_ANYWHERE) - return vlc_object_find (p_this->p_libvlc, i_type, FIND_CHILD); + return vlc_object_find (VLC_OBJECT(p_this->p_libvlc), i_type, FIND_CHILD); switch (i_type) { @@ -523,10 +535,11 @@ vlc_object_t *vlc_object_find_name( vlc_object_t *p_this, return p_found; } +#undef vlc_object_hold /** * Increment an object reference counter. */ -void * __vlc_object_hold( vlc_object_t *p_this ) +void * vlc_object_hold( vlc_object_t *p_this ) { vlc_object_internals_t *internals = vlc_internals( p_this ); @@ -539,11 +552,12 @@ void * __vlc_object_hold( vlc_object_t *p_this ) return p_this; } +#undef vlc_object_release /***************************************************************************** * Decrement an object refcount * And destroy the object if its refcount reach zero. *****************************************************************************/ -void __vlc_object_release( vlc_object_t *p_this ) +void vlc_object_release( vlc_object_t *p_this ) { vlc_object_internals_t *internals = vlc_internals( p_this ); vlc_object_t *parent = NULL; @@ -595,26 +609,45 @@ void __vlc_object_release( vlc_object_t *p_this ) } } +#undef vlc_object_attach /** **************************************************************************** * attach object to a parent object ***************************************************************************** * This function sets p_this as a child of p_parent, and p_parent as a parent - * of p_this. This link can be undone using vlc_object_detach. + * of p_this. *****************************************************************************/ -void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent ) +void vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent ) { if( !p_this ) return; vlc_object_internals_t *pap = vlc_internals (p_parent); vlc_object_internals_t *priv = vlc_internals (p_this); + vlc_object_t *p_old_parent; priv->prev = NULL; vlc_object_hold (p_parent); libvlc_lock (p_this->p_libvlc); +#ifndef NDEBUG + /* Reparenting an object carries a risk of invalid access to the parent, + * from another thread. This can happen when inheriting a variable, or + * through any direct access to vlc_object_t.p_parent. Also, reparenting + * brings a functional bug, whereby the reparented object uses incorrect + * old values for inherited variables (as the new parent may have different + * variable values, especially if it is an input). + * Note that the old parent may be already destroyed. + * So its pointer must not be dereferenced. + */ + if (priv->old_parent) + msg_Info (p_this, "Reparenting an object is dangerous (%p -> %p)!", + priv->old_parent, p_parent); +#endif + + p_old_parent = p_this->p_parent; + if (p_old_parent) + vlc_object_detach_unlocked (p_this); /* Attach the parent to its child */ - assert (!p_this->p_parent); p_this->p_parent = p_parent; /* Attach the child to its parent */ @@ -623,6 +656,9 @@ void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent ) priv->next->prev = priv; pap->first = priv; libvlc_unlock (p_this->p_libvlc); + + if (p_old_parent) + vlc_object_release (p_old_parent); } @@ -642,37 +678,19 @@ static void vlc_object_detach_unlocked (vlc_object_t *p_this) priv->next->prev = priv->prev; /* Remove p_this's parent */ +#ifndef NDEBUG + priv->old_parent = p_this->p_parent; +#endif p_this->p_parent = NULL; } - -/** - **************************************************************************** - * detach object from its parent - ***************************************************************************** - * This function removes all links between an object and its parent. - *****************************************************************************/ -void __vlc_object_detach( vlc_object_t *p_this ) -{ - vlc_object_t *p_parent; - if( !p_this ) return; - - libvlc_lock (p_this->p_libvlc); - p_parent = p_this->p_parent; - if (p_parent) - vlc_object_detach_unlocked( p_this ); - libvlc_unlock (p_this->p_libvlc); - - if (p_parent) - vlc_object_release (p_parent); -} - +#undef vlc_list_children /** * Gets the list of children of an objects, and increment their reference * count. * @return a list (possibly empty) or NULL in case of error. */ -vlc_list_t *__vlc_list_children( vlc_object_t *obj ) +vlc_list_t *vlc_list_children( vlc_object_t *obj ) { vlc_list_t *l; vlc_object_internals_t *priv; @@ -719,6 +737,7 @@ static void DumpVariable (const void *data, const VISIT which, const int depth) MYCASE( VARIABLE, "variable" ); MYCASE( FLOAT, "float" ); MYCASE( TIME, "time" ); + MYCASE( COORDS, "coords" ); MYCASE( ADDRESS, "address" ); MYCASE( MUTEX, "mutex" ); MYCASE( LIST, "list" ); @@ -754,6 +773,10 @@ static void DumpVariable (const void *data, const VISIT which, const int depth) case VLC_VAR_TIME: printf( ": %"PRIi64, (int64_t)p_var->val.i_time ); break; + case VLC_VAR_COORDS: + printf( ": %"PRId32"x%"PRId32, + p_var->val.coords.x, p_var->val.coords.y ); + break; case VLC_VAR_ADDRESS: printf( ": %p", p_var->val.p_address ); break;