rtpjitterbuffer: Avoid deadlock on flush
authorEdward Hervey <edward@centricular.com>
Sat, 30 May 2020 06:55:19 +0000 (08:55 +0200)
committerEdward Hervey <bilboed@bilboed.com>
Mon, 8 Jun 2020 11:34:26 +0000 (13:34 +0200)
When a GST_EVENT_FLUSH_START reaches the jitterbuffer, there is a chance that
our task is currently blocking waiting for a timer.

There was two problems:
* That wait wasn't checking for flushing situations
* The flushing handling wasn't waking up that conditional (to check whether it
should abort)

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/608>

gst/rtpmanager/gstrtpjitterbuffer.c

index ddfe0ed..03f2c7f 100644 (file)
@@ -1565,6 +1565,7 @@ gst_rtp_jitter_buffer_flush_start (GstRtpJitterBuffer * jitterbuffer)
   JBUF_SIGNAL_EVENT (priv);
   JBUF_SIGNAL_QUERY (priv, FALSE);
   JBUF_SIGNAL_QUEUE (priv);
+  JBUF_SIGNAL_TIMER (priv);
   JBUF_UNLOCK (priv);
 }
 
@@ -3490,6 +3491,8 @@ pop_and_push_next (GstRtpJitterBuffer * jitterbuffer, guint seqnum)
       /* Stopping timers */
       unschedule_current_timer (jitterbuffer);
       JBUF_WAIT_TIMER (priv);
+      if (G_UNLIKELY (priv->srcresult != GST_FLOW_OK))
+        goto early_out;
     }
   }
 
@@ -3512,7 +3515,7 @@ pop_and_push_next (GstRtpJitterBuffer * jitterbuffer, guint seqnum)
       GST_BUFFER_DTS (outbuf) = GST_CLOCK_TIME_NONE;
       result = gst_pad_push (priv->srcpad, outbuf);
 
-      JBUF_LOCK_CHECK (priv, out_flushing);
+      JBUF_LOCK_CHECK (priv, early_out);
       break;
     case ITEM_TYPE_LOST:
     case ITEM_TYPE_EVENT:
@@ -3534,7 +3537,7 @@ pop_and_push_next (GstRtpJitterBuffer * jitterbuffer, guint seqnum)
 
       result = GST_FLOW_OK;
 
-      JBUF_LOCK_CHECK (priv, out_flushing);
+      JBUF_LOCK_CHECK (priv, early_out);
       break;
     case ITEM_TYPE_QUERY:
     {
@@ -3542,7 +3545,7 @@ pop_and_push_next (GstRtpJitterBuffer * jitterbuffer, guint seqnum)
 
       res = gst_pad_peer_query (priv->srcpad, outquery);
 
-      JBUF_LOCK_CHECK (priv, out_flushing);
+      JBUF_LOCK_CHECK (priv, early_out);
       result = GST_FLOW_OK;
       GST_LOG_OBJECT (jitterbuffer, "did query %p, return %d", outquery, res);
       JBUF_SIGNAL_QUERY (priv, res);
@@ -3552,7 +3555,7 @@ pop_and_push_next (GstRtpJitterBuffer * jitterbuffer, guint seqnum)
   return result;
 
   /* ERRORS */
-out_flushing:
+early_out:
   {
     return priv->srcresult;
   }