X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fobjects.c;h=65802c77c74cb3d89bc5e3e96acfaf90ac5149c1;hb=7e39dc8b10afd76ab1b40844d971cdcb63e8d843;hp=d44eac15019dbb639cde5645c812003c36373b28;hpb=1e87443a23c8402521dbfc53bac436a8aff23dae;p=vlc diff --git a/src/misc/objects.c b/src/misc/objects.c index d44eac1501..65802c77c7 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 @@ -86,7 +90,6 @@ static void DumpStructure( vlc_object_internals_t *, unsigned, char * ); static vlc_list_t * NewList ( int ); static void vlc_object_destroy( vlc_object_t *p_this ); -static void vlc_object_detach_unlocked (vlc_object_t *p_this); /***************************************************************************** * Local structure lock @@ -101,8 +104,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,9 +158,6 @@ 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 ); @@ -189,7 +190,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 @@ -198,8 +199,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 ); @@ -253,9 +254,6 @@ static void vlc_object_destroy( vlc_object_t *p_this ) { vlc_object_internals_t *p_priv = vlc_internals( p_this ); - /* Objects are always detached beforehand */ - assert( !p_this->p_parent ); - /* Send a kill to the object's thread if applicable */ vlc_object_kill( p_this ); @@ -355,8 +353,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 { @@ -369,17 +370,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; @@ -406,14 +408,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; @@ -426,7 +428,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) { @@ -526,10 +528,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 ); @@ -542,11 +545,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; @@ -576,10 +580,18 @@ void __vlc_object_release( vlc_object_t *p_this ) if( b_should_destroy ) { + /* Detach from parent to protect against FIND_CHILDREN */ parent = p_this->p_parent; - if (parent) - /* Detach from parent to protect against FIND_CHILDREN */ - vlc_object_detach_unlocked (p_this); + if (likely(parent)) + { + /* Unlink */ + if (internals->prev != NULL) + internals->prev->next = internals->next; + else + vlc_internals(parent)->first = internals->next; + if (internals->next != NULL) + internals->next->prev = internals->prev; + } /* We have no children */ assert (internals->first == NULL); @@ -598,44 +610,27 @@ 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 == NULL); p_this->p_parent = p_parent; /* Attach the child to its parent */ @@ -644,62 +639,16 @@ 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); -} - - -static void vlc_object_detach_unlocked (vlc_object_t *p_this) -{ - assert (p_this->p_parent != NULL); - - vlc_object_internals_t *pap = vlc_internals (p_this->p_parent); - vlc_object_internals_t *priv = vlc_internals (p_this); - - /* Unlink */ - if (priv->prev != NULL) - priv->prev->next = priv->next; - else - pap->first = priv->next; - if (priv->next != NULL) - 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; } -#undef vlc_object_detach -/** - **************************************************************************** - * 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; @@ -746,9 +695,9 @@ 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" ); #undef MYCASE } printf( " *-o \"%s\" (%s", p_var->psz_name, psz_type ); @@ -770,7 +719,7 @@ static void DumpVariable (const void *data, const VISIT which, const int depth) printf( ": %s", p_var->val.b_bool ? "true" : "false" ); break; case VLC_VAR_INTEGER: - printf( ": %d", p_var->val.i_int ); + printf( ": %"PRId64, p_var->val.i_int ); break; case VLC_VAR_STRING: printf( ": \"%s\"", p_var->val.psz_string ); @@ -781,12 +730,13 @@ 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; - case VLC_VAR_LIST: - fputs( ": TODO", stdout ); - break; } fputc( '\n', stdout ); }