summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Schmidt <jan@centricular.com>2020-10-31 02:19:07 +1100
committerTim-Philipp Müller <tim@centricular.com>2020-10-31 11:40:08 +0000
commit21f0da0b642900f9967fda891551f6b2c66adbca (patch)
treeb2e2e72df67e52623a0dc9db58648fdf25940765
parent09ab239ebdd9791518b6aee1ffdf1e6b509ca890 (diff)
downloadgstreamer-plugins-good-21f0da0b642900f9967fda891551f6b2c66adbca.tar.gz
splitmuxsink: Don't use the element state lock
Using the element state lock to avoid splitmuxsink shutting down while doing element manipulations can lead to a deadlock on shutdown if a fragment switch happens at exactly the wrong moment. Use a private mutex and a shutdown boolean instead. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/799>
-rw-r--r--gst/multifile/gstsplitmuxsink.c27
-rw-r--r--gst/multifile/gstsplitmuxsink.h4
2 files changed, 28 insertions, 3 deletions
diff --git a/gst/multifile/gstsplitmuxsink.c b/gst/multifile/gstsplitmuxsink.c
index 675d7b749..02342cbba 100644
--- a/gst/multifile/gstsplitmuxsink.c
+++ b/gst/multifile/gstsplitmuxsink.c
@@ -80,6 +80,9 @@
GST_DEBUG_CATEGORY_STATIC (splitmux_debug);
#define GST_CAT_DEFAULT splitmux_debug
+#define GST_SPLITMUX_STATE_LOCK(s) g_mutex_lock(&(s)->state_lock)
+#define GST_SPLITMUX_STATE_UNLOCK(s) g_mutex_unlock(&(s)->state_lock)
+
#define GST_SPLITMUX_LOCK(s) g_mutex_lock(&(s)->lock)
#define GST_SPLITMUX_UNLOCK(s) g_mutex_unlock(&(s)->lock)
#define GST_SPLITMUX_WAIT_INPUT(s) g_cond_wait (&(s)->input_cond, &(s)->lock)
@@ -577,6 +580,7 @@ static void
gst_splitmux_sink_init (GstSplitMuxSink * splitmux)
{
g_mutex_init (&splitmux->lock);
+ g_mutex_init (&splitmux->state_lock);
g_cond_init (&splitmux->input_cond);
g_cond_init (&splitmux->output_cond);
g_queue_init (&splitmux->out_cmd_q);
@@ -650,6 +654,7 @@ gst_splitmux_sink_finalize (GObject * object)
g_cond_clear (&splitmux->input_cond);
g_cond_clear (&splitmux->output_cond);
g_mutex_clear (&splitmux->lock);
+ g_mutex_clear (&splitmux->state_lock);
g_queue_foreach (&splitmux->out_cmd_q, (GFunc) out_cmd_buf_free, NULL);
g_queue_clear (&splitmux->out_cmd_q);
@@ -1899,7 +1904,14 @@ start_next_fragment (GstSplitMuxSink * splitmux, MqStreamCtx * ctx)
sink = gst_object_ref (splitmux->active_sink);
GST_SPLITMUX_UNLOCK (splitmux);
- GST_STATE_LOCK (splitmux);
+ GST_SPLITMUX_STATE_LOCK (splitmux);
+
+ if (splitmux->shutdown) {
+ GST_DEBUG_OBJECT (splitmux,
+ "Shutdown requested. Aborting fragment switch.");
+ GST_SPLITMUX_STATE_UNLOCK (splitmux);
+ return;
+ }
if (splitmux->async_finalize) {
if (splitmux->muxed_out_bytes > 0
@@ -2012,7 +2024,7 @@ start_next_fragment (GstSplitMuxSink * splitmux, MqStreamCtx * ctx)
gst_object_unref (muxer);
GST_SPLITMUX_LOCK (splitmux);
- GST_STATE_UNLOCK (splitmux);
+ GST_SPLITMUX_STATE_UNLOCK (splitmux);
splitmux->switching_fragment = FALSE;
do_async_done (splitmux);
@@ -2030,7 +2042,7 @@ start_next_fragment (GstSplitMuxSink * splitmux, MqStreamCtx * ctx)
return;
fail:
- GST_STATE_UNLOCK (splitmux);
+ GST_SPLITMUX_STATE_UNLOCK (splitmux);
GST_ELEMENT_ERROR (splitmux, RESOURCE, SETTINGS,
("Could not create the new muxer/sink"), NULL);
}
@@ -3549,12 +3561,21 @@ gst_splitmux_sink_change_state (GstElement * element, GstStateChange transition)
splitmux->output_state = SPLITMUX_OUTPUT_STATE_START_NEXT_FILE;
GST_SPLITMUX_UNLOCK (splitmux);
+
+ GST_SPLITMUX_STATE_LOCK (splitmux);
+ splitmux->shutdown = FALSE;
+ GST_SPLITMUX_STATE_UNLOCK (splitmux);
break;
}
case GST_STATE_CHANGE_PAUSED_TO_READY:
g_atomic_int_set (&(splitmux->split_requested), FALSE);
g_atomic_int_set (&(splitmux->do_split_next_gop), FALSE);
+
case GST_STATE_CHANGE_READY_TO_NULL:
+ GST_SPLITMUX_STATE_LOCK (splitmux);
+ splitmux->shutdown = TRUE;
+ GST_SPLITMUX_STATE_UNLOCK (splitmux);
+
GST_SPLITMUX_LOCK (splitmux);
gst_splitmux_sink_reset (splitmux);
splitmux->output_state = SPLITMUX_OUTPUT_STATE_STOPPED;
diff --git a/gst/multifile/gstsplitmuxsink.h b/gst/multifile/gstsplitmuxsink.h
index bd629bdd0..e1cc14c72 100644
--- a/gst/multifile/gstsplitmuxsink.h
+++ b/gst/multifile/gstsplitmuxsink.h
@@ -105,7 +105,11 @@ struct _GstSplitMuxSink
{
GstBin parent;
+ GMutex state_lock;
+ gboolean shutdown;
+
GMutex lock;
+
GCond input_cond;
GCond output_cond;