[vlc-devel] [PATCH] libvlc: dump object types abd names when leaking

Thomas Guillem thomas at gllm.fr
Thu Feb 21 10:24:57 CET 2019


Comment:
A lot of developers asked me to propose this patch again. It was previously
refused because developers could use proper debugging tools. I disagree with
that assumption. Even with Asan, when the leak assert fail, it will abort()
without prompting any leaks, so you'll have to edit libvlc.c to remove this
assert. If your leak was not reproducible, you'll lose a precious information.
And good luck finding the leak with GDB, you really need to know the internal
of vlc_object_t to iterate through the different list to get the culprit.

Commit log:

In case of a vlc_object_t leak, and if asserts are enabled, the error output
will be like the following (when leaking intentionally decoder_t objects):

=== vlc_object LEAKS detected ===
  \ playlist
  |   \ input
  |   |   \ decoder avcodec
  |   |   | decoder faad
  |   |   | decoder stl
---
 src/libvlc.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/src/libvlc.c b/src/libvlc.c
index 8e8d2ca8b2..d9ff96de84 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -436,6 +436,24 @@ void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
 #endif
 }
 
+#ifndef NDEBUG
+static void DumpObjectLeaks(vlc_object_internals_t *priv, unsigned level)
+{
+    bool first = true;
+    vlc_list_foreach(priv, &priv->children, siblings)
+    {
+        vlc_object_t *obj = vlc_externals(priv);
+        for (unsigned i = 0; i < level; i++)
+            fprintf(stderr, "  %s ", first && i == level -1 ? "\\" : "|");
+        char *name = vlc_object_get_name(obj);
+        fprintf(stderr, "%s %s\n", vlc_object_typename(obj), name ? name : "");
+        free(name);
+        DumpObjectLeaks(priv, level + 1);
+        first = false;
+    }
+}
+#endif
+
 /**
  * Destroy everything.
  * This function requests the running threads to finish, waits for their
@@ -449,6 +467,18 @@ void libvlc_InternalDestroy( libvlc_int_t *p_libvlc )
 
     vlc_ExitDestroy( &priv->exit );
 
+#ifndef NDEBUG
+    {
+        vlc_object_internals_t *internal = vlc_internals(p_libvlc);
+        if (atomic_load(&internal->refs) != 1)
+        {
+            vlc_mutex_lock(&internal->tree_lock);
+            fprintf(stderr, "=== vlc_object LEAKS detected ===\n");
+            DumpObjectLeaks(internal, 1);
+            vlc_mutex_unlock(&internal->tree_lock);
+        }
+    }
+#endif
     assert( atomic_load(&(vlc_internals(p_libvlc)->refs)) == 1 );
     vlc_object_release( p_libvlc );
 }
-- 
2.20.1



More information about the vlc-devel mailing list