From af90778314be73ca036d7ce716642303085c3ee7 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 30 Oct 2020 16:31:18 +1100 Subject: [PATCH] webrtc: Fix a race on shutdown. The main context can disappear in gst_webrtc_bin_enqueue_task() between checking the is_closed flag and enqueueing a source on the main context. Protect the main context with the object lock instead of the PC lock, and hold a ref briefly to make sure it stays alive. Part-of: --- ext/webrtc/gstwebrtcbin.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/ext/webrtc/gstwebrtcbin.c b/ext/webrtc/gstwebrtcbin.c index 9531e42d45..baded4cd1f 100644 --- a/ext/webrtc/gstwebrtcbin.c +++ b/ext/webrtc/gstwebrtcbin.c @@ -713,9 +713,12 @@ _gst_pc_thread (GstWebRTCBin * webrtc) * tasks */ g_main_loop_run (webrtc->priv->loop); - PC_LOCK (webrtc); + GST_OBJECT_LOCK (webrtc); g_main_context_unref (webrtc->priv->main_context); webrtc->priv->main_context = NULL; + GST_OBJECT_UNLOCK (webrtc); + + PC_LOCK (webrtc); g_main_loop_unref (webrtc->priv->loop); webrtc->priv->loop = NULL; PC_COND_BROADCAST (webrtc); @@ -744,8 +747,11 @@ _start_thread (GstWebRTCBin * webrtc) static void _stop_thread (GstWebRTCBin * webrtc) { - PC_LOCK (webrtc); + GST_OBJECT_LOCK (webrtc); webrtc->priv->is_closed = TRUE; + GST_OBJECT_UNLOCK (webrtc); + + PC_LOCK (webrtc); g_main_loop_quit (webrtc->priv->loop); while (webrtc->priv->loop) PC_COND_WAIT (webrtc); @@ -804,16 +810,22 @@ gst_webrtc_bin_enqueue_task (GstWebRTCBin * webrtc, GstWebRTCBinFunc func, gpointer data, GDestroyNotify notify, GstPromise * promise) { GstWebRTCBinTask *op; + GMainContext *ctx; GSource *source; g_return_val_if_fail (GST_IS_WEBRTC_BIN (webrtc), FALSE); + GST_OBJECT_LOCK (webrtc); if (webrtc->priv->is_closed) { + GST_OBJECT_UNLOCK (webrtc); GST_DEBUG_OBJECT (webrtc, "Peerconnection is closed, aborting execution"); if (notify) notify (data); return FALSE; } + ctx = g_main_context_ref (webrtc->priv->main_context); + GST_OBJECT_UNLOCK (webrtc); + op = g_new0 (GstWebRTCBinTask, 1); op->webrtc = webrtc; op->op = func; @@ -826,8 +838,9 @@ gst_webrtc_bin_enqueue_task (GstWebRTCBin * webrtc, GstWebRTCBinFunc func, g_source_set_priority (source, G_PRIORITY_DEFAULT); g_source_set_callback (source, (GSourceFunc) _execute_op, op, (GDestroyNotify) _free_op); - g_source_attach (source, webrtc->priv->main_context); + g_source_attach (source, ctx); g_source_unref (source); + g_main_context_unref (ctx); return TRUE; }