summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2019-10-21 17:56:14 +0300
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>2019-12-04 08:24:04 +0000
commit7af50da2c9b94f00063877c582c0b34578feb7b5 (patch)
tree76378d93a148e22381d03c99716623673fdf9619
parent4a554a2a68e6e7b7d062dc7caf37a52a13e35d82 (diff)
downloadgstreamer-7af50da2c9b94f00063877c582c0b34578feb7b5.tar.gz
bus: Use new GSource dispose function
Without this it is possible that we have a GSource with reference count 0 stored in the GstBus that is currently in the process of being destroyed. gst_bus_remove_watch() might then access it, increase its reference count to 1 again, call GSource API on it and then unref it, which will then finalize it a second time. The dispose function allows the GSource to be resurrected until it returned so the above would be safe now. This caused some spurious crashes during shutdown in various applications.
-rw-r--r--gst/gstbus.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/gst/gstbus.c b/gst/gstbus.c
index 4553288c60..a10b89c917 100644
--- a/gst/gstbus.c
+++ b/gst/gstbus.c
@@ -852,20 +852,40 @@ no_handler:
}
}
+#if GLIB_CHECK_VERSION(2,63,3)
static void
-gst_bus_source_finalize (GSource * source)
+gst_bus_source_dispose (GSource * source)
{
GstBusSource *bsource = (GstBusSource *) source;
GstBus *bus;
bus = bsource->bus;
+ GST_DEBUG_OBJECT (bus, "disposing source %p", source);
+
+ GST_OBJECT_LOCK (bus);
+ if (bus->priv->signal_watch == source)
+ bus->priv->signal_watch = NULL;
+ GST_OBJECT_UNLOCK (bus);
+}
+#endif
+
+static void
+gst_bus_source_finalize (GSource * source)
+{
+ GstBusSource *bsource = (GstBusSource *) source;
+#if !GLIB_CHECK_VERSION(2,63,3)
+ GstBus *bus = bsource->bus;
+#endif
+
GST_DEBUG_OBJECT (bus, "finalize source %p", source);
+#if !GLIB_CHECK_VERSION(2,63,3)
GST_OBJECT_LOCK (bus);
if (bus->priv->signal_watch == source)
bus->priv->signal_watch = NULL;
GST_OBJECT_UNLOCK (bus);
+#endif
gst_object_unref (bsource->bus);
bsource->bus = NULL;
@@ -900,6 +920,9 @@ gst_bus_create_watch (GstBus * bus)
sizeof (GstBusSource));
g_source_set_name ((GSource *) source, "GStreamer message bus watch");
+#if GLIB_CHECK_VERSION(2,63,3)
+ g_source_set_dispose_function ((GSource *) source, gst_bus_source_dispose);
+#endif
source->bus = gst_object_ref (bus);
g_source_add_poll ((GSource *) source, &bus->priv->pollfd);