mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
rtpbin: Make cleaning up sources in rtp_session_on_timeout MT safe
Using _foreach_remove on the hashtable, while releasing the lock protecting that table inside the callback is not a good idea. The hashtable might then change (a source removed or added) while signals like on_timeout are being sent. This solution makes a copy of the table, performs the _foreach without actually removing any sources, but marks them for removal on a second iteration with the real list, but this time not letting go of the lock. Fixes #630452
This commit is contained in:
parent
87a9d7f679
commit
ca6a512b5e
3 changed files with 32 additions and 4 deletions
|
@ -2360,7 +2360,7 @@ session_report_blocks (const gchar * key, RTPSource * source, ReportData * data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* perform cleanup of sources that timed out */
|
/* perform cleanup of sources that timed out */
|
||||||
static gboolean
|
static void
|
||||||
session_cleanup (const gchar * key, RTPSource * source, ReportData * data)
|
session_cleanup (const gchar * key, RTPSource * source, ReportData * data)
|
||||||
{
|
{
|
||||||
gboolean remove = FALSE;
|
gboolean remove = FALSE;
|
||||||
|
@ -2428,7 +2428,8 @@ session_cleanup (const gchar * key, RTPSource * source, ReportData * data)
|
||||||
if (sendertimeout)
|
if (sendertimeout)
|
||||||
on_sender_timeout (sess, source);
|
on_sender_timeout (sess, source);
|
||||||
}
|
}
|
||||||
return remove;
|
|
||||||
|
source->closing = remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2556,6 +2557,18 @@ is_rtcp_time (RTPSession * sess, GstClockTime current_time, ReportData * data)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clone_ssrcs_hashtable (gchar * key, RTPSource * source, GHashTable * hash_table)
|
||||||
|
{
|
||||||
|
g_hash_table_insert (hash_table, key, g_object_ref (source));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
remove_closing_sources (const gchar * key, RTPSource * source, gpointer * data)
|
||||||
|
{
|
||||||
|
return source->closing;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rtp_session_on_timeout:
|
* rtp_session_on_timeout:
|
||||||
* @sess: an #RTPSession
|
* @sess: an #RTPSession
|
||||||
|
@ -2581,6 +2594,7 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time,
|
||||||
GstFlowReturn result = GST_FLOW_OK;
|
GstFlowReturn result = GST_FLOW_OK;
|
||||||
ReportData data;
|
ReportData data;
|
||||||
RTPSource *own;
|
RTPSource *own;
|
||||||
|
GHashTable *table_copy;
|
||||||
gboolean notify = FALSE;
|
gboolean notify = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (RTP_IS_SESSION (sess), GST_FLOW_ERROR);
|
g_return_val_if_fail (RTP_IS_SESSION (sess), GST_FLOW_ERROR);
|
||||||
|
@ -2602,9 +2616,21 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time,
|
||||||
/* get a new interval, we need this for various cleanups etc */
|
/* get a new interval, we need this for various cleanups etc */
|
||||||
data.interval = calculate_rtcp_interval (sess, TRUE, sess->first_rtcp);
|
data.interval = calculate_rtcp_interval (sess, TRUE, sess->first_rtcp);
|
||||||
|
|
||||||
/* first perform cleanups */
|
/* Make a local copy of the hashtable. We need to do this because the
|
||||||
|
* cleanup stage below releases the session lock. */
|
||||||
|
table_copy = g_hash_table_new_full (NULL, NULL, NULL,
|
||||||
|
(GDestroyNotify) g_object_unref);
|
||||||
|
g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
|
||||||
|
(GHFunc) clone_ssrcs_hashtable, table_copy);
|
||||||
|
|
||||||
|
/* Clean up the session, mark the source for removing, this might release the
|
||||||
|
* session lock. */
|
||||||
|
g_hash_table_foreach (table_copy, (GHFunc) session_cleanup, &data);
|
||||||
|
g_hash_table_destroy (table_copy);
|
||||||
|
|
||||||
|
/* Now remove the marked sources */
|
||||||
g_hash_table_foreach_remove (sess->ssrcs[sess->mask_idx],
|
g_hash_table_foreach_remove (sess->ssrcs[sess->mask_idx],
|
||||||
(GHRFunc) session_cleanup, &data);
|
(GHRFunc) remove_closing_sources, NULL);
|
||||||
|
|
||||||
/* see if we need to generate SR or RR packets */
|
/* see if we need to generate SR or RR packets */
|
||||||
if (is_rtcp_time (sess, current_time, &data)) {
|
if (is_rtcp_time (sess, current_time, &data)) {
|
||||||
|
|
|
@ -158,6 +158,7 @@ rtp_source_init (RTPSource * src)
|
||||||
src->validated = FALSE;
|
src->validated = FALSE;
|
||||||
src->internal = FALSE;
|
src->internal = FALSE;
|
||||||
src->probation = RTP_DEFAULT_PROBATION;
|
src->probation = RTP_DEFAULT_PROBATION;
|
||||||
|
src->closing = FALSE;
|
||||||
|
|
||||||
src->sdes = gst_structure_new ("application/x-rtp-source-sdes", NULL);
|
src->sdes = gst_structure_new ("application/x-rtp-source-sdes", NULL);
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,7 @@ struct _RTPSource {
|
||||||
gboolean internal;
|
gboolean internal;
|
||||||
gboolean is_csrc;
|
gboolean is_csrc;
|
||||||
gboolean is_sender;
|
gboolean is_sender;
|
||||||
|
gboolean closing;
|
||||||
|
|
||||||
GstStructure *sdes;
|
GstStructure *sdes;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue