[rhythmbox] gst: Don't leak bus in RBEncoderGst



commit 5f4f6a62b5084a0073ed545290e351e867e5c73e
Author: Christophe Fergeau <cfergeau redhat com>
Date:   Mon Jul 8 10:40:54 2013 +0200

    gst: Don't leak bus in RBEncoderGst
    
    When starting the GstPipeline in RBEncoderGst, the associated GstBus
    was not correctly unreffed. gst_pipeline_get_bus() returns a reference
    to the bus object so it must be released after use. Most importantly,
    as described in https://bugzilla.gnome.org/show_bug.cgi?id=683470 ,
    we must make sure to remove the bus watch from the main loop
    when we no longer need it, or this will cause the GstBus being watched
    not to be properly disposed of.
    In my testing, this was causing leaks of 2 fds per track transferred.
    As the default max fd per process is 1024, this means that after about
    500 tracks transferred, rhythmbox would get in big troubles as it
    can no longer open new file descriptors.

 backends/gstreamer/rb-encoder-gst.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)
---
diff --git a/backends/gstreamer/rb-encoder-gst.c b/backends/gstreamer/rb-encoder-gst.c
index 64cfa4c..7a81114 100644
--- a/backends/gstreamer/rb-encoder-gst.c
+++ b/backends/gstreamer/rb-encoder-gst.c
@@ -53,6 +53,7 @@ struct _RBEncoderGstPrivate {
 
        GstElement *encodebin;
        GstElement *pipeline;
+       guint bus_watch_id;
 
        gboolean transcoding;
        gint decoded_pads;
@@ -273,7 +274,9 @@ start_pipeline (RBEncoderGst *encoder)
        g_assert (encoder->priv->pipeline != NULL);
 
        bus = gst_pipeline_get_bus (GST_PIPELINE (encoder->priv->pipeline));
-       gst_bus_add_watch (bus, bus_watch_cb, encoder);
+       g_assert(encoder->priv->bus_watch_id == 0);
+       encoder->priv->bus_watch_id = gst_bus_add_watch (bus, bus_watch_cb, encoder);
+       g_object_unref (bus);
 
        result = gst_element_set_state (encoder->priv->pipeline, GST_STATE_PLAYING);
        if (result != GST_STATE_CHANGE_FAILURE) {
@@ -836,6 +839,11 @@ impl_finalize (GObject *object)
        if (encoder->priv->progress_id != 0)
                g_source_remove (encoder->priv->progress_id);
 
+       if (encoder->priv->bus_watch_id != 0) {
+               g_source_remove (encoder->priv->bus_watch_id);
+               encoder->priv->bus_watch_id = 0;
+       }
+
        if (encoder->priv->pipeline) {
                gst_element_set_state (encoder->priv->pipeline, GST_STATE_NULL);
                g_object_unref (encoder->priv->pipeline);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]