diff options
author | Jan Schmidt <jan@centricular.com> | 2020-10-30 16:31:18 +1100 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.com> | 2020-10-31 12:31:26 +0000 |
commit | f14d39064cfd5df78eee4a8cf8edba3006f2074a (patch) | |
tree | 0ef0e586bac72b6f2122016aeafab6a4490315ef | |
parent | 73a23c92ad89ec72f06eca284199c8c56dafc098 (diff) | |
download | gstreamer-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.c | 19 |
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; } |