[vlc-devel] [PATCH 3/6] vout: check pools leaks

Thomas Guillem thomas at gllm.fr
Thu Jan 5 14:37:41 CET 2017


Show an error message and assert if filters, decoders or vout displays leak
pictures.

There is one limitation, leaks won't be detected for vout displays without
direct rendering.
---
 src/misc/picture_pool.c         | 17 +++++++++++++++--
 src/misc/picture_pool.h         | 11 +++++++++++
 src/video_output/video_output.c | 22 +++++++++++++++++++++-
 src/video_output/vout_wrapper.c |  6 +++++-
 4 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/src/misc/picture_pool.c b/src/misc/picture_pool.c
index 527da051e9..3d5e6a37ff 100644
--- a/src/misc/picture_pool.c
+++ b/src/misc/picture_pool.c
@@ -50,14 +50,17 @@ struct picture_pool_t {
     picture_t  *picture[];
 };
 
-static void picture_pool_Destroy(picture_pool_t *pool)
+static bool picture_pool_Destroy(picture_pool_t *pool)
 {
     if (atomic_fetch_sub(&pool->refs, 1) != 1)
-        return;
+        return false;
+
+    assert(pool->picture_count - popcountll(pool->available) == 0);
 
     vlc_cond_destroy(&pool->wait);
     vlc_mutex_destroy(&pool->lock);
     vlc_free(pool);
+    return true;
 }
 
 void picture_pool_Release(picture_pool_t *pool)
@@ -67,6 +70,16 @@ void picture_pool_Release(picture_pool_t *pool)
     picture_pool_Destroy(pool);
 }
 
+void picture_pool_IncRef(picture_pool_t *pool)
+{
+    atomic_fetch_add(&pool->refs, 1);
+}
+
+bool picture_pool_DecRef(picture_pool_t *pool)
+{
+    return picture_pool_Destroy(pool);
+}
+
 static void picture_pool_ReleasePicture(picture_t *clone)
 {
     picture_priv_t *priv = (picture_priv_t *)clone;
diff --git a/src/misc/picture_pool.h b/src/misc/picture_pool.h
index 35a14e7895..4296970f29 100644
--- a/src/misc/picture_pool.h
+++ b/src/misc/picture_pool.h
@@ -40,3 +40,14 @@ unsigned picture_pool_Reset( picture_pool_t * );
  * picture_pool_Reset will also reset the cancel state to false.
  */
 void picture_pool_Cancel( picture_pool_t *, bool canceled );
+
+/**
+ * Increments the reference count of the pool
+ */
+void picture_pool_IncRef(picture_pool_t *);
+
+/**
+ * Decrements the reference count of the pool
+ * @return true if the pool is destroyed (reference count to 0).
+ */
+bool picture_pool_DecRef(picture_pool_t *);
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 84972dbfda..f9631eb3e9 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -1474,7 +1474,27 @@ static void ThreadStop(vout_thread_t *vout, vout_display_state_t *state)
 
     if (vout->p->decoder_fifo)
         picture_fifo_Delete(vout->p->decoder_fifo);
-    assert(!vout->p->decoder_pool);
+
+    vout_thread_sys_t *sys = vout->p;
+    if (sys->decoder_pool)
+    {
+        /* The decoder and the vout display modules are closed. The vout thread
+         * should be the only one that still hold references on the private and
+         * the decoder pools. Time to check for leaks. */
+        assert(sys->private_pool);
+
+        bool leak;
+        leak = !picture_pool_DecRef(sys->private_pool);
+        if (leak)
+            msg_Err(vout, "private_pool pictures leaked");
+        assert(!leak);
+
+        leak = !picture_pool_DecRef(sys->decoder_pool);
+        if (leak)
+            msg_Err(vout, "decoder_pool pictures leaked");
+        assert(!leak);
+        sys->private_pool = sys->decoder_pool = NULL;
+    }
 }
 
 static void ThreadInit(vout_thread_t *vout)
diff --git a/src/video_output/vout_wrapper.c b/src/video_output/vout_wrapper.c
index 310f50cdc6..05557cf4f0 100644
--- a/src/video_output/vout_wrapper.c
+++ b/src/video_output/vout_wrapper.c
@@ -35,6 +35,7 @@
 #include <assert.h>
 #include "vout_internal.h"
 #include "display.h"
+#include "../misc/picture_pool.h"
 
 /*****************************************************************************
  * Local prototypes
@@ -94,7 +95,6 @@ void vout_CloseWrapper(vout_thread_t *vout, vout_display_state_t *state)
 #ifdef _WIN32
     var_DelCallback(vout, "video-wallpaper", Forward, NULL);
 #endif
-    sys->decoder_pool = NULL; /* FIXME remove */
 
     vout_DeleteDisplay(sys->display.vd, state);
     free(sys->display.title);
@@ -147,6 +147,7 @@ int vout_InitWrapper(vout_thread_t *vout)
         sys->dpb_size     = picture_pool_GetSize(display_pool) - reserved_picture;
         sys->decoder_pool = display_pool;
         sys->display_pool = display_pool;
+        picture_pool_IncRef(display_pool);
     } else if (!sys->decoder_pool) {
         sys->decoder_pool =
             picture_pool_NewFromFormat(&source,
@@ -160,6 +161,7 @@ int vout_InitWrapper(vout_thread_t *vout)
         } else {
             sys->dpb_size = picture_pool_GetSize(sys->decoder_pool) - reserved_picture;
         }
+        picture_pool_IncRef(sys->decoder_pool);
         NoDrInit(vout);
     }
     sys->private_pool = picture_pool_Reserve(sys->decoder_pool, private_picture);
@@ -167,9 +169,11 @@ int vout_InitWrapper(vout_thread_t *vout)
     {
         if (sys->decoder_pool != sys->display_pool)
             picture_pool_Release(sys->decoder_pool);
+        picture_pool_DecRef(sys->decoder_pool);
         sys->display_pool = sys->decoder_pool = NULL;
         return VLC_EGENERIC;
     }
+    picture_pool_IncRef(sys->private_pool);
     return VLC_SUCCESS;
 }
 
-- 
2.11.0



More information about the vlc-devel mailing list