Commit 559c876b authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

One child is one reference

Avoid objects being detached asynchronously too early.
Side effect is that you cannot free your children in the destructor
(that would be a reference loop).
parent d2ea1609
...@@ -633,6 +633,7 @@ void * __vlc_object_yield( vlc_object_t *p_this ) ...@@ -633,6 +633,7 @@ void * __vlc_object_yield( vlc_object_t *p_this )
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_internals_t *internals = vlc_internals( p_this );
vlc_object_t *parent = NULL;
bool b_should_destroy; bool b_should_destroy;
vlc_spin_lock( &internals->ref_spin ); vlc_spin_lock( &internals->ref_spin );
...@@ -659,6 +660,10 @@ void __vlc_object_release( vlc_object_t *p_this ) ...@@ -659,6 +660,10 @@ void __vlc_object_release( vlc_object_t *p_this )
if( b_should_destroy ) if( b_should_destroy )
{ {
/* We have no children */
assert (internals->i_children == 0);
parent = p_this->p_parent;
#ifndef NDEBUG #ifndef NDEBUG
if( VLC_OBJECT(p_this->p_libvlc) == p_this ) if( VLC_OBJECT(p_this->p_libvlc) == p_this )
{ {
...@@ -687,25 +692,21 @@ void __vlc_object_release( vlc_object_t *p_this ) ...@@ -687,25 +692,21 @@ void __vlc_object_release( vlc_object_t *p_this )
vlc_internals (internals->next)->prev = internals->prev; vlc_internals (internals->next)->prev = internals->prev;
vlc_internals (internals->prev)->next = internals->next; vlc_internals (internals->prev)->next = internals->next;
/* Detach from parent to protect against FIND_CHILDREN */ if (parent)
vlc_object_detach_unlocked (p_this); /* Detach from parent to protect against FIND_CHILDREN */
/* Detach from children to protect against FIND_PARENT */ vlc_object_detach_unlocked (p_this);
for (int i = 0; i < internals->i_children; i++)
internals->pp_children[i]->p_parent = NULL;
} }
vlc_mutex_unlock( &structure_lock ); vlc_mutex_unlock( &structure_lock );
if( b_should_destroy ) if( b_should_destroy )
{ {
int canc; int canc;
free( internals->pp_children );
internals->pp_children = NULL;
internals->i_children = 0;
canc = vlc_savecancel (); canc = vlc_savecancel ();
vlc_object_destroy( p_this ); vlc_object_destroy( p_this );
vlc_restorecancel (canc); vlc_restorecancel (canc);
if (parent)
vlc_object_release (parent);
} }
} }
...@@ -720,6 +721,7 @@ void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent ) ...@@ -720,6 +721,7 @@ void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
{ {
if( !p_this ) return; if( !p_this ) return;
vlc_object_yield (p_parent);
vlc_mutex_lock( &structure_lock ); vlc_mutex_lock( &structure_lock );
/* Attach the parent to its child */ /* Attach the parent to its child */
...@@ -785,14 +787,17 @@ static void vlc_object_detach_unlocked (vlc_object_t *p_this) ...@@ -785,14 +787,17 @@ static void vlc_object_detach_unlocked (vlc_object_t *p_this)
*****************************************************************************/ *****************************************************************************/
void __vlc_object_detach( vlc_object_t *p_this ) void __vlc_object_detach( vlc_object_t *p_this )
{ {
vlc_object_t *p_parent;
if( !p_this ) return; if( !p_this ) return;
vlc_mutex_lock( &structure_lock ); vlc_mutex_lock( &structure_lock );
if( !p_this->p_parent ) p_parent = p_this->p_parent;
msg_Err( p_this, "object is not attached" ); if (p_parent)
else
vlc_object_detach_unlocked( p_this ); vlc_object_detach_unlocked( p_this );
vlc_mutex_unlock( &structure_lock ); vlc_mutex_unlock( &structure_lock );
if (p_parent)
vlc_object_release (p_parent);
} }
......
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