queue: Only unblock upstream waiting for the query once downstream is finished

... when flushing and deactivating pads. Otherwise downstream might have a
query that was already unreffed by upstream, causing crashes or other
interesting effects.

https://bugzilla.gnome.org/show_bug.cgi?id=763496
This commit is contained in:
Sebastian Dröge 2016-03-11 16:04:52 +02:00
parent d184e7a9a0
commit 722ad08733
2 changed files with 14 additions and 11 deletions

View file

@ -933,14 +933,20 @@ gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
/* unblock the loop and chain functions */ /* unblock the loop and chain functions */
GST_QUEUE_SIGNAL_ADD (queue); GST_QUEUE_SIGNAL_ADD (queue);
GST_QUEUE_SIGNAL_DEL (queue); GST_QUEUE_SIGNAL_DEL (queue);
queue->last_query = FALSE;
g_cond_signal (&queue->query_handled);
GST_QUEUE_MUTEX_UNLOCK (queue); GST_QUEUE_MUTEX_UNLOCK (queue);
/* make sure it pauses, this should happen since we sent /* make sure it pauses, this should happen since we sent
* flush_start downstream. */ * flush_start downstream. */
gst_pad_pause_task (queue->srcpad); gst_pad_pause_task (queue->srcpad);
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped"); GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped");
/* unblock query handler after the streaming thread is shut down.
* Otherwise downstream might have a query that is already unreffed
* upstream */
GST_QUEUE_MUTEX_LOCK (queue);
queue->last_query = FALSE;
g_cond_signal (&queue->query_handled);
GST_QUEUE_MUTEX_UNLOCK (queue);
break; break;
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
STATUS (queue, pad, "received flush stop event"); STATUS (queue, pad, "received flush stop event");
@ -1676,10 +1682,7 @@ gst_queue_sink_activate_mode (GstPad * pad, GstObject * parent, GstPadMode mode,
GST_QUEUE_MUTEX_LOCK (queue); GST_QUEUE_MUTEX_LOCK (queue);
queue->srcresult = GST_FLOW_FLUSHING; queue->srcresult = GST_FLOW_FLUSHING;
/* the item del signal will unblock */ /* the item del signal will unblock */
g_cond_signal (&queue->item_del); GST_QUEUE_SIGNAL_DEL (queue);
/* unblock query handler */
queue->last_query = FALSE;
g_cond_signal (&queue->query_handled);
GST_QUEUE_MUTEX_UNLOCK (queue); GST_QUEUE_MUTEX_UNLOCK (queue);
/* step 2, wait until streaming thread stopped and flush queue */ /* step 2, wait until streaming thread stopped and flush queue */

View file

@ -2395,14 +2395,17 @@ gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent,
/* unblock the loop and chain functions */ /* unblock the loop and chain functions */
GST_QUEUE2_SIGNAL_ADD (queue); GST_QUEUE2_SIGNAL_ADD (queue);
GST_QUEUE2_SIGNAL_DEL (queue); GST_QUEUE2_SIGNAL_DEL (queue);
queue->last_query = FALSE;
g_cond_signal (&queue->query_handled);
GST_QUEUE2_MUTEX_UNLOCK (queue); GST_QUEUE2_MUTEX_UNLOCK (queue);
/* make sure it pauses, this should happen since we sent /* make sure it pauses, this should happen since we sent
* flush_start downstream. */ * flush_start downstream. */
gst_pad_pause_task (queue->srcpad); gst_pad_pause_task (queue->srcpad);
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped"); GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped");
GST_QUEUE2_MUTEX_LOCK (queue);
queue->last_query = FALSE;
g_cond_signal (&queue->query_handled);
GST_QUEUE2_MUTEX_UNLOCK (queue);
} else { } else {
GST_QUEUE2_MUTEX_LOCK (queue); GST_QUEUE2_MUTEX_LOCK (queue);
/* flush the sink pad */ /* flush the sink pad */
@ -3373,9 +3376,6 @@ gst_queue2_sink_activate_mode (GstPad * pad, GstObject * parent,
queue->srcresult = GST_FLOW_FLUSHING; queue->srcresult = GST_FLOW_FLUSHING;
queue->sinkresult = GST_FLOW_FLUSHING; queue->sinkresult = GST_FLOW_FLUSHING;
GST_QUEUE2_SIGNAL_DEL (queue); GST_QUEUE2_SIGNAL_DEL (queue);
/* Unblock query handler */
queue->last_query = FALSE;
g_cond_signal (&queue->query_handled);
GST_QUEUE2_MUTEX_UNLOCK (queue); GST_QUEUE2_MUTEX_UNLOCK (queue);
/* wait until it is unblocked and clean up */ /* wait until it is unblocked and clean up */