Commit 523ef308 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

The totally dumb reference checker

parent 1746fdda
...@@ -46,6 +46,11 @@ void system_End ( libvlc_int_t * ); ...@@ -46,6 +46,11 @@ void system_End ( libvlc_int_t * );
int vlc_threads_init( void ); int vlc_threads_init( void );
void vlc_threads_end( void ); void vlc_threads_end( void );
vlc_object_t *vlc_threadobj (void); vlc_object_t *vlc_threadobj (void);
#ifndef NDEBUG
void vlc_refcheck (vlc_object_t *obj);
#else
# define vlc_refcheck( obj ) (void)0
#endif
/* /*
* CPU capabilities * CPU capabilities
......
...@@ -1469,3 +1469,58 @@ static void ListChildren( vlc_list_t *p_list, vlc_object_t *p_this, int i_type ) ...@@ -1469,3 +1469,58 @@ static void ListChildren( vlc_list_t *p_list, vlc_object_t *p_this, int i_type )
ListChildren( p_list, p_tmp, i_type ); ListChildren( p_list, p_tmp, i_type );
} }
} }
#ifndef NDEBUG
void vlc_refcheck (vlc_object_t *obj)
{
static unsigned errors = 0;
vlc_object_t *caller = vlc_threadobj ();
vlc_object_internals_t *priv = vlc_internals (obj);
int refs;
if (errors > 100)
return;
if (!caller)
return; /* main thread, not sure how to handle it */
/* An object can always access itself without reference! */
if (caller == obj)
return;
/* The calling thread is younger than the object.
* Access could be valid, we would need more accounting. */
if (caller->i_object_id > obj->i_object_id)
return;
vlc_spin_lock (&priv->ref_spin);
refs = priv->i_refcount;
vlc_spin_unlock (&priv->ref_spin);
/* Object has more than one reference.
* The current thread could be holding a valid reference. */
if (refs > 1)
return;
/* The parent of an object normally holds the unique reference.
* As not all objects are threads, it could also be an ancestor. */
vlc_mutex_lock (&structure_lock);
for (vlc_object_t *cur = obj; cur != NULL; cur = cur->p_parent)
if (cur == caller)
{
vlc_mutex_unlock (&structure_lock);
return;
}
vlc_mutex_unlock (&structure_lock);
#if 1
if (caller->i_object_type == VLC_OBJECT_PLAYLIST)
return; /* Playlist is too clever, or hopelessly broken. */
#endif
msg_Err (caller, "This thread is accessing...");
msg_Err (obj, "...this object in a suspicious manner.");
if (++errors == 100)
msg_Err (caller, "Too many reference errors");
}
#endif
...@@ -168,6 +168,7 @@ int __var_Create( vlc_object_t *p_this, const char *psz_name, int i_type ) ...@@ -168,6 +168,7 @@ int __var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
static vlc_list_t dummy_null_list = {0, NULL, NULL}; static vlc_list_t dummy_null_list = {0, NULL, NULL};
vlc_object_internals_t *p_priv = vlc_internals( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this );
vlc_refcheck( p_this );
vlc_mutex_lock( &p_priv->var_lock ); vlc_mutex_lock( &p_priv->var_lock );
/* FIXME: if the variable already exists, we don't duplicate it. But we /* FIXME: if the variable already exists, we don't duplicate it. But we
...@@ -331,6 +332,7 @@ int __var_Destroy( vlc_object_t *p_this, const char *psz_name ) ...@@ -331,6 +332,7 @@ int __var_Destroy( vlc_object_t *p_this, const char *psz_name )
variable_t *p_var; variable_t *p_var;
vlc_object_internals_t *p_priv = vlc_internals( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this );
vlc_refcheck( p_this );
vlc_mutex_lock( &p_priv->var_lock ); vlc_mutex_lock( &p_priv->var_lock );
i_var = GetUnused( p_this, psz_name ); i_var = GetUnused( p_this, psz_name );
...@@ -407,6 +409,7 @@ int __var_Change( vlc_object_t *p_this, const char *psz_name, ...@@ -407,6 +409,7 @@ int __var_Change( vlc_object_t *p_this, const char *psz_name,
vlc_value_t oldval; vlc_value_t oldval;
vlc_object_internals_t *p_priv = vlc_internals( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this );
vlc_refcheck( p_this );
vlc_mutex_lock( &p_priv->var_lock ); vlc_mutex_lock( &p_priv->var_lock );
i_var = Lookup( p_priv->p_vars, p_priv->i_vars, psz_name ); i_var = Lookup( p_priv->p_vars, p_priv->i_vars, psz_name );
...@@ -759,6 +762,7 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val ) ...@@ -759,6 +762,7 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val )
vlc_value_t oldval; vlc_value_t oldval;
vlc_object_internals_t *p_priv = vlc_internals( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this );
vlc_refcheck( p_this );
vlc_mutex_lock( &p_priv->var_lock ); vlc_mutex_lock( &p_priv->var_lock );
i_var = GetUnused( p_this, psz_name ); i_var = GetUnused( p_this, psz_name );
...@@ -836,6 +840,7 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val ) ...@@ -836,6 +840,7 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
variable_t *p_var; variable_t *p_var;
vlc_object_internals_t *p_priv = vlc_internals( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this );
vlc_refcheck( p_this );
vlc_mutex_lock( &p_priv->var_lock ); vlc_mutex_lock( &p_priv->var_lock );
i_var = Lookup( p_priv->p_vars, p_priv->i_vars, psz_name ); i_var = Lookup( p_priv->p_vars, p_priv->i_vars, psz_name );
...@@ -902,6 +907,7 @@ int __var_AddCallback( vlc_object_t *p_this, const char *psz_name, ...@@ -902,6 +907,7 @@ int __var_AddCallback( vlc_object_t *p_this, const char *psz_name,
callback_entry_t entry; callback_entry_t entry;
vlc_object_internals_t *p_priv = vlc_internals( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this );
vlc_refcheck( p_this );
entry.pf_callback = pf_callback; entry.pf_callback = pf_callback;
entry.p_data = p_data; entry.p_data = p_data;
...@@ -939,6 +945,7 @@ int __var_DelCallback( vlc_object_t *p_this, const char *psz_name, ...@@ -939,6 +945,7 @@ int __var_DelCallback( vlc_object_t *p_this, const char *psz_name,
variable_t *p_var; variable_t *p_var;
vlc_object_internals_t *p_priv = vlc_internals( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this );
vlc_refcheck( p_this );
vlc_mutex_lock( &p_priv->var_lock ); vlc_mutex_lock( &p_priv->var_lock );
i_var = GetUnused( p_this, psz_name ); i_var = GetUnused( p_this, psz_name );
...@@ -1575,6 +1582,7 @@ int __var_Command( vlc_object_t *p_this, const char *psz_name, ...@@ -1575,6 +1582,7 @@ int __var_Command( vlc_object_t *p_this, const char *psz_name,
return VLC_ENOOBJ; return VLC_ENOOBJ;
} }
vlc_refcheck( p_this );
i_type = var_Type( p_obj, psz_cmd ); i_type = var_Type( p_obj, psz_cmd );
if( !( i_type&VLC_VAR_ISCOMMAND ) ) if( !( i_type&VLC_VAR_ISCOMMAND ) )
{ {
......
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