]> git.sesse.net Git - vlc/blobdiff - src/misc/objects.c
Fix previous commit
[vlc] / src / misc / objects.c
index 982c1e7ceb1ef09da227438314130a0bd21bac51..03bbd6a245c7b2fed4b5d7d065c198f86f76b7b6 100644 (file)
@@ -81,13 +81,14 @@ static void           ListChildren  ( vlc_list_t *, vlc_object_t *, int );
 static void vlc_object_destroy( vlc_object_t *p_this );
 static void vlc_object_detach_unlocked (vlc_object_t *p_this);
 
-#ifndef NDEBUG
+#ifdef LIBVLC_REFCHECK
 static vlc_threadvar_t held_objects;
 typedef struct held_list_t
 {
     struct held_list_t *next;
     vlc_object_t *obj;
 } held_list_t;
+static void held_objects_destroy (void *);
 #endif
 
 /*****************************************************************************
@@ -150,9 +151,9 @@ void *vlc_custom_create( vlc_object_t *p_this, size_t i_size,
         p_libvlc_global->i_counter = 0;
         p_priv->next = p_priv->prev = p_new;
         vlc_mutex_init( &structure_lock );
-#ifndef NDEBUG
+#ifdef LIBVLC_REFCHECK
         /* TODO: use the destruction callback to track ref leaks */
-        vlc_threadvar_create( &held_objects, NULL );
+        vlc_threadvar_create( &held_objects, held_objects_destroy );
 #endif
     }
     else
@@ -182,7 +183,7 @@ void *vlc_custom_create( vlc_object_t *p_this, size_t i_size,
     p_priv->pipes[0] = p_priv->pipes[1] = -1;
 
     p_priv->next = VLC_OBJECT (p_libvlc_global);
-#if defined (NDEBUG)
+#if !defined (LIBVLC_REFCHECK)
     /* ... */
 #elif defined (LIBVLC_USE_PTHREAD)
     p_priv->creator_id = pthread_self ();
@@ -269,10 +270,6 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type )
             i_size = sizeof(aout_instance_t);
             psz_type = "audio output";
             break;
-        case VLC_OBJECT_SOUT:
-            i_size = sizeof(sout_instance_t);
-            psz_type = "stream output";
-            break;
         case VLC_OBJECT_OPENGL:
             i_size = sizeof( vout_thread_t );
             psz_type = "opengl";
@@ -383,7 +380,8 @@ static void vlc_object_destroy( vlc_object_t *p_this )
 
         /* We are the global object ... no need to lock. */
         vlc_mutex_destroy( &structure_lock );
-#ifndef NDEBUG
+#ifdef LIBVLC_REFCHECK
+        held_objects_destroy( vlc_threadvar_get( &held_objects ) );
         vlc_threadvar_delete( &held_objects );
 #endif
     }
@@ -661,6 +659,7 @@ void * vlc_object_get( int i_id )
 {
     libvlc_global_data_t *p_libvlc_global = vlc_global();
     vlc_object_t *obj = NULL;
+#ifndef NDEBUG
     vlc_object_t *caller = vlc_threadobj ();
 
     if (caller)
@@ -668,7 +667,7 @@ void * vlc_object_get( int i_id )
     else
         fprintf (stderr, "main thread uses deprecated vlc_object_get(%d)\n",
                  i_id);
-
+#endif
     vlc_mutex_lock( &structure_lock );
 
     for( obj = vlc_internals (p_libvlc_global)->next;
@@ -682,10 +681,12 @@ void * vlc_object_get( int i_id )
         }
     }
     obj = NULL;
+#ifndef NDEBUG
     if (caller)
         msg_Warn (caller, "wants non-existing object %d", i_id);
     else
         fprintf (stderr, "main thread wants non-existing object %d\n", i_id);
+#endif
 out:
     vlc_mutex_unlock( &structure_lock );
     return obj;
@@ -793,9 +794,10 @@ void __vlc_object_yield( vlc_object_t *p_this )
     /* Increment the counter */
     internals->i_refcount++;
     vlc_spin_unlock( &internals->ref_spin );
-#ifndef NDEBUG
+#ifdef LIBVLC_REFCHECK
     /* Update the list of referenced objects */
     /* Using TLS, so no need to lock */
+    /* The following line may leak memory if a thread leaks objects. */
     held_list_t *newhead = malloc (sizeof (*newhead));
     held_list_t *oldhead = vlc_threadvar_get (&held_objects);
     newhead->next = oldhead;
@@ -813,13 +815,13 @@ void __vlc_object_release( vlc_object_t *p_this )
     vlc_object_internals_t *internals = vlc_internals( p_this );
     bool b_should_destroy;
 
-#ifndef NDEBUG
+#ifdef LIBVLC_REFCHECK
     /* Update the list of referenced objects */
     /* Using TLS, so no need to lock */
     for (held_list_t *hlcur = vlc_threadvar_get (&held_objects),
                      *hlprev = NULL;
          hlcur != NULL;
-         hlcur = hlcur->next)
+         hlprev = hlcur, hlcur = hlcur->next)
     {
         if (hlcur->obj == p_this)
         {
@@ -903,15 +905,6 @@ void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
     INSERT_ELEM( priv->pp_children, priv->i_children, priv->i_children,
                  p_this );
 
-    /* Kill the object if parent is already dead.
-     * Note: We should surely lock parent here, but that would
-     * create quite a few dead lock case. Hopefully, it
-     * is perfectly safe to do it that way. We only risk
-     * receiving kill event twice. But given current API
-     * it is ok. */
-    if( p_this->p_parent->b_die )
-        vlc_object_kill( p_this );
-
     vlc_mutex_unlock( &structure_lock );
 }
 
@@ -1525,7 +1518,7 @@ static void ListChildren( vlc_list_t *p_list, vlc_object_t *p_this, int i_type )
     }
 }
 
-#ifndef NDEBUG
+#ifdef LIBVLC_REFCHECK
 # if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE)
 #  include <execinfo.h>
 # endif
@@ -1594,4 +1587,27 @@ void vlc_refcheck (vlc_object_t *obj)
     if (++errors == 100)
         fprintf (stderr, "Too many reference errors!\n");
 }
+
+static void held_objects_destroy (void *data)
+{
+    VLC_UNUSED( data );
+    held_list_t *hl = vlc_threadvar_get (&held_objects);
+    vlc_object_t *caller = vlc_threadobj ();
+
+    while (hl != NULL)
+    {
+        held_list_t *buf = hl->next;
+        vlc_object_t *obj = hl->obj;
+
+        fprintf (stderr, "The %s %s thread object leaked a reference to...\n"
+                         "the %s %s object.\n",
+                 caller && caller->psz_object_name
+                     ? caller->psz_object_name : "unnamed",
+                 caller ? caller->psz_object_type : "main",
+                 obj->psz_object_name ? obj->psz_object_name : "unnamed",
+                 obj->psz_object_type);
+        free (hl);
+        hl = buf;
+    }
+}
 #endif