summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim@centricular.com>2016-02-16 19:43:48 +0000
committerTim-Philipp Müller <tim@centricular.com>2016-02-20 10:11:02 +0000
commitb14464947ff200406786107ec5d130baa898b3aa (patch)
tree218e55842e777d6bea1eb45a4fe1fe2288dd7a12
parent1e779addd8dff7d0b357dff9d7975ae035d3f773 (diff)
downloadgstreamer-plugins-bad-b14464947ff200406786107ec5d130baa898b3aa.tar.gz
adaptivedemux: fix race on shutdown that could result in deadlocks
Minimal fix for one particular deadlock, adaptivedemux has seen a general re-work of its locking in git master, but that would be too intrusive to backport into the stable branch. We need to use a separate variable to signal cancellation here.
-rw-r--r--gst-libs/gst/adaptivedemux/gstadaptivedemux.c16
-rw-r--r--gst-libs/gst/adaptivedemux/gstadaptivedemux.h3
2 files changed, 15 insertions, 4 deletions
diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
index 9f74c658a..15d75e580 100644
--- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
+++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c
@@ -939,8 +939,12 @@ gst_adaptive_demux_stream_free (GstAdaptiveDemuxStream * stream)
GST_DEBUG_OBJECT (demux, "Leaving streaming task %s:%s",
GST_DEBUG_PAD_NAME (stream->pad));
- g_cond_signal (&stream->fragment_download_cond);
gst_task_stop (stream->download_task);
+
+ g_mutex_lock (&stream->fragment_download_lock);
+ stream->cancelled = TRUE;
+ g_cond_signal (&stream->fragment_download_cond);
+ g_mutex_unlock (&stream->fragment_download_lock);
}
GST_LOG_OBJECT (demux, "Waiting for task to finish");
gst_task_join (stream->download_task);
@@ -1305,6 +1309,11 @@ gst_adaptive_demux_start_tasks (GstAdaptiveDemux * demux)
demux->cancelled = FALSE;
for (iter = demux->streams; iter; iter = g_list_next (iter)) {
GstAdaptiveDemuxStream *stream = iter->data;
+
+ g_mutex_lock (&stream->fragment_download_lock);
+ stream->cancelled = FALSE;
+ g_mutex_unlock (&stream->fragment_download_lock);
+
stream->last_ret = GST_FLOW_OK;
gst_task_start (stream->download_task);
}
@@ -1333,7 +1342,7 @@ gst_adaptive_demux_stop_tasks (GstAdaptiveDemux * demux)
if (stream->src)
gst_element_set_state (stream->src, GST_STATE_READY);
g_mutex_lock (&stream->fragment_download_lock);
- stream->download_finished = TRUE;
+ stream->cancelled = TRUE;
g_cond_signal (&stream->fragment_download_cond);
g_mutex_unlock (&stream->fragment_download_lock);
}
@@ -1952,7 +1961,8 @@ gst_adaptive_demux_stream_download_uri (GstAdaptiveDemux * demux,
/* wait for the fragment to be completely downloaded */
GST_DEBUG_OBJECT (stream->pad,
"Waiting for fragment download to finish: %s", uri);
- while (!stream->demux->cancelled && !stream->download_finished) {
+ while (!stream->demux->cancelled && !stream->download_finished
+ && !stream->cancelled) {
g_cond_wait (&stream->fragment_download_cond,
&stream->fragment_download_lock);
}
diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h
index b65b6d675..e31a12537 100644
--- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h
+++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h
@@ -144,7 +144,8 @@ struct _GstAdaptiveDemuxStream
GstPad *src_srcpad;
GMutex fragment_download_lock;
GCond fragment_download_cond;
- gboolean download_finished;
+ gboolean download_finished; /* protected by fragment_download_lock */
+ gboolean cancelled; /* protected by fragment_download_lock */
gboolean starting_fragment;
gboolean first_fragment_buffer;
gint64 download_start_time;