rtmp2: Avoid a deadlock when getting stats
authorJan Alexander Steffens (heftig) <jsteffens@make.tv>
Wed, 8 Apr 2020 16:39:06 +0000 (18:39 +0200)
committerJan Alexander Steffens (heftig) <jsteffens@make.tv>
Wed, 8 Apr 2020 16:41:01 +0000 (18:41 +0200)
We need to do this without holding the lock as the `g_async_queue_pop`
waits on the loop thread to deliver the stats. The loop thread might
attempt to take the lock as well, leading to a deadlock.

Taking a reference to the connection should be enough to keep this
safe.

gst/rtmp2/gstrtmp2sink.c
gst/rtmp2/gstrtmp2src.c

index 8f6c794..de85944 100644 (file)
@@ -1144,7 +1144,18 @@ gst_rtmp2_sink_get_stats (GstRtmp2Sink * self)
   g_mutex_lock (&self->lock);
 
   if (self->connection) {
-    s = gst_rtmp_connection_get_stats (self->connection);
+    GstRtmpConnection *connection = g_object_ref (self->connection);
+
+    g_mutex_unlock (&self->lock);
+
+    /* We need to do this without holding the lock as the g_async_queue_pop
+     * waits on the loop thread to deliver the stats. The loop thread might
+     * attempt to take the lock as well, leading to a deadlock. */
+    s = gst_rtmp_connection_get_stats (connection);
+
+    g_mutex_lock (&self->lock);
+
+    g_object_unref (connection);
   } else if (self->stats) {
     s = gst_structure_copy (self->stats);
   } else {
index dff4eac..150b42f 100644 (file)
@@ -979,7 +979,18 @@ gst_rtmp2_src_get_stats (GstRtmp2Src * self)
   g_mutex_lock (&self->lock);
 
   if (self->connection) {
-    s = gst_rtmp_connection_get_stats (self->connection);
+    GstRtmpConnection *connection = g_object_ref (self->connection);
+
+    g_mutex_unlock (&self->lock);
+
+    /* We need to do this without holding the lock as the g_async_queue_pop
+     * waits on the loop thread to deliver the stats. The loop thread might
+     * attempt to take the lock as well, leading to a deadlock. */
+    s = gst_rtmp_connection_get_stats (connection);
+
+    g_mutex_lock (&self->lock);
+
+    g_object_unref (connection);
   } else if (self->stats) {
     s = gst_structure_copy (self->stats);
   } else {