From 6680b70781ebaafd2ce49db766b6012678b450eb Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Wed, 8 Apr 2020 18:39:06 +0200 Subject: [PATCH] rtmp2: Avoid a deadlock when getting stats 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 | 13 ++++++++++++- gst/rtmp2/gstrtmp2src.c | 13 ++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/gst/rtmp2/gstrtmp2sink.c b/gst/rtmp2/gstrtmp2sink.c index 8f6c794..de85944 100644 --- a/gst/rtmp2/gstrtmp2sink.c +++ b/gst/rtmp2/gstrtmp2sink.c @@ -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 { diff --git a/gst/rtmp2/gstrtmp2src.c b/gst/rtmp2/gstrtmp2src.c index dff4eac..150b42f 100644 --- a/gst/rtmp2/gstrtmp2src.c +++ b/gst/rtmp2/gstrtmp2src.c @@ -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 { -- 2.7.4