bus: Make sure to remove the GPollFD from the GSources when destroying the bus
authorSebastian Dröge <sebastian@centricular.com>
Mon, 29 Feb 2016 08:01:50 +0000 (10:01 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Mon, 29 Feb 2016 11:41:15 +0000 (13:41 +0200)
Otherwise the GSource can look into our already destroyed bus where the
GPollFD is stored.

https://bugzilla.gnome.org/show_bug.cgi?id=762849

gst/gstbus.c

index d24a935..294c7d3 100644 (file)
@@ -119,6 +119,8 @@ struct _GstBusPrivate
   gboolean enable_async;
   GstPoll *poll;
   GPollFD pollfd;
+
+  GList *sources;
 };
 
 #define gst_bus_parent_class parent_class
@@ -233,6 +235,7 @@ gst_bus_dispose (GObject * object)
 
   if (bus->priv->queue) {
     GstMessage *message;
+    GList *l;
 
     g_mutex_lock (&bus->priv->queue_lock);
     do {
@@ -245,6 +248,13 @@ gst_bus_dispose (GObject * object)
     g_mutex_unlock (&bus->priv->queue_lock);
     g_mutex_clear (&bus->priv->queue_lock);
 
+    GST_OBJECT_LOCK (bus);
+    for (l = bus->priv->sources; l; l = l->next)
+      g_source_remove_poll (l->data, &bus->priv->pollfd);
+    g_list_free (bus->priv->sources);
+    bus->priv->sources = NULL;
+    GST_OBJECT_UNLOCK (bus);
+
     if (bus->priv->poll)
       gst_poll_free (bus->priv->poll);
     bus->priv->poll = NULL;
@@ -833,6 +843,7 @@ gst_bus_source_finalize (GSource * source)
     GST_OBJECT_LOCK (bus);
     if (bus->priv->signal_watch == source)
       bus->priv->signal_watch = NULL;
+    bus->priv->sources = g_list_remove (bus->priv->sources, source);
     GST_OBJECT_UNLOCK (bus);
 
     g_object_unref (bus);
@@ -847,6 +858,26 @@ static GSourceFuncs gst_bus_source_funcs = {
   gst_bus_source_finalize
 };
 
+static GSource *
+gst_bus_create_watch_unlocked (GstBus * bus)
+{
+  GstBusSource *source;
+
+  g_return_val_if_fail (GST_IS_BUS (bus), NULL);
+  g_return_val_if_fail (bus->priv->poll != NULL, NULL);
+
+  source = (GstBusSource *) g_source_new (&gst_bus_source_funcs,
+      sizeof (GstBusSource));
+
+  g_source_set_name ((GSource *) source, "GStreamer message bus watch");
+
+  g_weak_ref_init (&source->bus_ref, (GObject *) bus);
+  bus->priv->sources = g_list_prepend (bus->priv->sources, source);
+  g_source_add_poll ((GSource *) source, &bus->priv->pollfd);
+
+  return (GSource *) source;
+}
+
 /**
  * gst_bus_create_watch:
  * @bus: a #GstBus to create the watch for
@@ -860,18 +891,14 @@ static GSourceFuncs gst_bus_source_funcs = {
 GSource *
 gst_bus_create_watch (GstBus * bus)
 {
-  GstBusSource *source;
+  GSource *source;
 
   g_return_val_if_fail (GST_IS_BUS (bus), NULL);
   g_return_val_if_fail (bus->priv->poll != NULL, NULL);
 
-  source = (GstBusSource *) g_source_new (&gst_bus_source_funcs,
-      sizeof (GstBusSource));
-
-  g_source_set_name ((GSource *) source, "GStreamer message bus watch");
-
-  g_weak_ref_init (&source->bus_ref, (GObject *) bus);
-  g_source_add_poll ((GSource *) source, &bus->priv->pollfd);
+  GST_OBJECT_LOCK (bus);
+  source = gst_bus_create_watch_unlocked (bus);
+  GST_OBJECT_UNLOCK (bus);
 
   return (GSource *) source;
 }
@@ -891,7 +918,7 @@ gst_bus_add_watch_full_unlocked (GstBus * bus, gint priority,
     return 0;
   }
 
-  source = gst_bus_create_watch (bus);
+  source = gst_bus_create_watch_unlocked (bus);
   if (!source) {
     g_critical ("Creating bus watch failed");
     return 0;