rtsp-stream: clear backlog when removing transport
authorMathieu Duponchelle <mathieu@centricular.com>
Fri, 14 Feb 2020 13:59:25 +0000 (14:59 +0100)
committerMathieu Duponchelle <mduponchelle1@gmail.com>
Mon, 24 Feb 2020 20:24:29 +0000 (20:24 +0000)
This ensures we don't end up calling any of transports' callbacks
with a potentially unreffed user_data (in practice, a client that
may have been removed)

gst/rtsp-server/rtsp-server-internal.h
gst/rtsp-server/rtsp-stream-transport.c
gst/rtsp-server/rtsp-stream.c

index 03b02e2..056814f 100644 (file)
@@ -42,6 +42,8 @@ gboolean                 gst_rtsp_stream_transport_backlog_pop   (GstRTSPStreamT
 
 gboolean                 gst_rtsp_stream_transport_backlog_is_empty (GstRTSPStreamTransport *trans);
 
+void                     gst_rtsp_stream_transport_clear_backlog (GstRTSPStreamTransport * trans);
+
 void                     gst_rtsp_stream_transport_lock_backlog  (GstRTSPStreamTransport * trans);
 
 void                     gst_rtsp_stream_transport_unlock_backlog (GstRTSPStreamTransport * trans);
index 8ce16dd..ac0e257 100644 (file)
@@ -882,7 +882,8 @@ gst_rtsp_stream_transport_backlog_push (GstRTSPStreamTransport * trans,
 
 /* Not MT-safe, caller should ensure consistent locking (see
  * gst_rtsp_stream_transport_lock_backlog()). Ownership
- * of @buffer and @buffer_list is transfered back to the caller */
+ * of @buffer and @buffer_list is transfered back to the caller,
+ * if either of those is NULL the underlying object is unreffed */
 gboolean
 gst_rtsp_stream_transport_backlog_pop (GstRTSPStreamTransport * trans,
     GstBuffer ** buffer, GstBufferList ** buffer_list, gboolean * is_rtp)
@@ -899,9 +900,18 @@ gst_rtsp_stream_transport_backlog_pop (GstRTSPStreamTransport * trans,
 
   priv->first_rtp_timestamp = get_first_backlog_timestamp (trans);
 
-  *buffer = item->buffer;
-  *buffer_list = item->buffer_list;
-  *is_rtp = item->is_rtp;
+  if (buffer)
+    *buffer = item->buffer;
+  else if (item->buffer)
+    gst_buffer_unref (item->buffer);
+
+  if (buffer_list)
+    *buffer_list = item->buffer_list;
+  else if (item->buffer_list)
+    gst_buffer_list_unref (item->buffer_list);
+
+  if (is_rtp)
+    *is_rtp = item->is_rtp;
 
   return TRUE;
 }
@@ -914,6 +924,16 @@ gst_rtsp_stream_transport_backlog_is_empty (GstRTSPStreamTransport * trans)
   return gst_queue_array_is_empty (trans->priv->items);
 }
 
+/* Not MT-safe, caller should ensure consistent locking.
+ * See gst_rtsp_stream_transport_lock_backlog() */
+void
+gst_rtsp_stream_transport_clear_backlog (GstRTSPStreamTransport * trans)
+{
+  while (!gst_rtsp_stream_transport_backlog_is_empty (trans)) {
+    gst_rtsp_stream_transport_backlog_pop (trans, NULL, NULL, NULL);
+  }
+}
+
 /* Internal API, protects access to the TCP backlog. Safe to
  * call recursively */
 void
index dc484e3..ad18f14 100644 (file)
@@ -4607,6 +4607,11 @@ update_transport (GstRTSPStream * stream, GstRTSPStreamTransport * trans,
       } else {
         GST_INFO ("removing TCP %s", tr->destination);
         priv->transports = g_list_delete_link (priv->transports, tr_element);
+
+        gst_rtsp_stream_transport_lock_backlog (trans);
+        gst_rtsp_stream_transport_clear_backlog (trans);
+        gst_rtsp_stream_transport_unlock_backlog (trans);
+
         priv->n_tcp_transports--;
       }
       priv->transports_cookie++;