rtsp-stream: clear backlog when removing transport

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)
This commit is contained in:
Mathieu Duponchelle 2020-02-14 14:59:25 +01:00 committed by Mathieu Duponchelle
parent 54b6b3bcab
commit fa41cbe9a4
3 changed files with 31 additions and 4 deletions

View 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);

View 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,8 +900,17 @@ gst_rtsp_stream_transport_backlog_pop (GstRTSPStreamTransport * trans,
priv->first_rtp_timestamp = get_first_backlog_timestamp (trans);
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

View 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++;