summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Schmidt <jan@centricular.com>2020-10-30 16:31:18 +1100
committerTim-Philipp Müller <tim@centricular.com>2020-10-31 12:31:26 +0000
commitf14d39064cfd5df78eee4a8cf8edba3006f2074a (patch)
tree0ef0e586bac72b6f2122016aeafab6a4490315ef
parent73a23c92ad89ec72f06eca284199c8c56dafc098 (diff)
downloadgstreamer-plugins-bad-f14d39064cfd5df78eee4a8cf8edba3006f2074a.tar.gz
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: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1746>
-rw-r--r--ext/webrtc/gstwebrtcbin.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/ext/webrtc/gstwebrtcbin.c b/ext/webrtc/gstwebrtcbin.c
index d281b29ef..f1c8b7914 100644
--- a/ext/webrtc/gstwebrtcbin.c
+++ b/ext/webrtc/gstwebrtcbin.c
@@ -699,9 +699,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);
@@ -730,8 +733,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);
@@ -790,16 +796,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;
@@ -812,8 +824,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;
}