[farsight2/master] Protect rtpsession dispose with a rw lock
Olivier Crête
olivier.crete at collabora.co.uk
Fri Jan 9 11:26:36 PST 2009
---
gst/fsrtpconference/fs-rtp-session.c | 140 +++++++++++++++++++++++++++++++++-
1 files changed, 137 insertions(+), 3 deletions(-)
diff --git a/gst/fsrtpconference/fs-rtp-session.c b/gst/fsrtpconference/fs-rtp-session.c
index 0f8dde3..c92aa6e 100644
--- a/gst/fsrtpconference/fs-rtp-session.c
+++ b/gst/fsrtpconference/fs-rtp-session.c
@@ -187,6 +187,8 @@ struct _FsRtpSessionPrivate
GError *construction_error;
+ /* Can only be used while using the lock */
+ GStaticRWLock disposed_lock;
gboolean disposed;
};
@@ -370,6 +372,8 @@ fs_rtp_session_init (FsRtpSession *self)
self->mutex = g_mutex_new ();
+ g_static_rw_lock_init (&self->priv->disposed_lock);
+
self->priv->media_type = FS_MEDIA_TYPE_LAST + 1;
self->priv->no_rtcp_timeout = DEFAULT_NO_RTCP_TIMEOUT;
@@ -435,11 +439,15 @@ fs_rtp_session_dispose (GObject *object)
GList *item = NULL;
GstBin *conferencebin = NULL;
+ g_static_rw_lock_writer_lock (&self->priv->disposed_lock);
if (self->priv->disposed)
{
/* If dispose did already run, return. */
+ g_static_rw_lock_writer_unlock (&self->priv->disposed_lock);
return;
}
+ g_static_rw_lock_writer_unlock (&self->priv->disposed_lock);
+
conferencebin = GST_BIN (self->priv->conference);
@@ -671,9 +679,34 @@ fs_rtp_session_finalize (GObject *object)
if (self->priv->ssrc_streams)
g_hash_table_destroy (self->priv->ssrc_streams);
+ g_static_rw_lock_free (&self->priv->disposed_lock);
+
parent_class->finalize (object);
}
+static gboolean
+fs_rtp_session_has_disposed_enter (FsRtpSession *self, GError **error)
+{
+ g_static_rw_lock_reader_lock (&self->priv->disposed_lock);
+
+ if (self->priv->disposed)
+ {
+ g_static_rw_lock_reader_unlock (&self->priv->disposed_lock);
+ g_set_error (error, FS_ERROR, FS_ERROR_DISPOSED,
+ "Called function after session has been disposed");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static void
+fs_rtp_session_has_disposed_exit (FsRtpSession *self)
+{
+ g_static_rw_lock_reader_unlock (&self->priv->disposed_lock);
+}
+
static void
fs_rtp_session_get_property (GObject *object,
guint prop_id,
@@ -682,6 +715,9 @@ fs_rtp_session_get_property (GObject *object,
{
FsRtpSession *self = FS_RTP_SESSION (object);
+ if (fs_rtp_session_has_disposed_enter (self, NULL))
+ return;
+
switch (prop_id)
{
case PROP_MEDIA_TYPE:
@@ -751,6 +787,8 @@ fs_rtp_session_get_property (GObject *object,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
+
+ fs_rtp_session_has_disposed_exit (self);
}
static void
@@ -761,6 +799,9 @@ fs_rtp_session_set_property (GObject *object,
{
FsRtpSession *self = FS_RTP_SESSION (object);
+ if (fs_rtp_session_has_disposed_enter (self, NULL))
+ return;
+
switch (prop_id)
{
case PROP_MEDIA_TYPE:
@@ -781,6 +822,8 @@ fs_rtp_session_set_property (GObject *object,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
+
+ fs_rtp_session_has_disposed_exit (self);
}
static void
@@ -1347,6 +1390,9 @@ _stream_known_source_packet_received (FsRtpStream *stream, guint component,
guint32 ssrc;
FsRtpSession *self = FS_RTP_SESSION_CAST (user_data);
+ if (fs_rtp_session_has_disposed_enter (self, NULL))
+ return;
+
if (component == 1)
{
if (gst_rtp_buffer_validate (buffer))
@@ -1375,6 +1421,7 @@ _stream_known_source_packet_received (FsRtpStream *stream, guint component,
}
/* We would have jumped to OK if we had a valid packet */
+ fs_rtp_session_has_disposed_exit (self);
return;
ok:
@@ -1396,6 +1443,7 @@ _stream_known_source_packet_received (FsRtpStream *stream, guint component,
FS_RTP_SESSION_UNLOCK (self);
}
+ fs_rtp_session_has_disposed_exit (self);
}
static gboolean
@@ -1410,6 +1458,9 @@ _remove_stream (gpointer user_data,
{
FsRtpSession *self = FS_RTP_SESSION (user_data);
+ if (fs_rtp_session_has_disposed_enter (self, NULL))
+ return;
+
FS_RTP_SESSION_LOCK (self);
self->priv->streams =
g_list_remove_all (self->priv->streams, where_the_object_was);
@@ -1418,6 +1469,8 @@ _remove_stream (gpointer user_data,
g_hash_table_foreach_remove (self->priv->ssrc_streams, _remove_stream_from_ht,
where_the_object_was);
FS_RTP_SESSION_UNLOCK (self);
+
+ fs_rtp_session_has_disposed_exit (self);
}
/**
@@ -1454,13 +1507,20 @@ fs_rtp_session_new_stream (FsSession *session,
"You have to provide a participant of type RTP");
return NULL;
}
+
+ if (fs_rtp_session_has_disposed_enter (self, error))
+ return NULL;
+
rtpparticipant = FS_RTP_PARTICIPANT (participant);
st = fs_rtp_session_get_new_stream_transmitter (self, transmitter,
participant, n_parameters, parameters, error);
if (!st)
+ {
+ fs_rtp_session_has_disposed_exit (self);
return NULL;
+ }
new_stream = FS_STREAM_CAST (fs_rtp_stream_new (self, rtpparticipant,
direction, st, _stream_new_remote_codecs,
@@ -1473,6 +1533,7 @@ fs_rtp_session_new_stream (FsSession *session,
g_object_weak_ref (G_OBJECT (new_stream), _remove_stream, self);
+ fs_rtp_session_has_disposed_exit (self);
return new_stream;
}
@@ -1501,11 +1562,15 @@ fs_rtp_session_start_telephony_event (FsSession *session, guint8 event,
FsRtpSession *self = FS_RTP_SESSION (session);
gboolean ret = FALSE;
+ if (fs_rtp_session_has_disposed_enter (self, NULL))
+ return FALSE;
+
FS_RTP_SESSION_LOCK (self);
ret = fs_rtp_special_sources_start_telephony_event (
self->priv->extra_sources, event, volume, method);
FS_RTP_SESSION_UNLOCK (self);
+ fs_rtp_session_has_disposed_exit (self);
return ret;
}
@@ -1529,11 +1594,15 @@ fs_rtp_session_stop_telephony_event (FsSession *session, FsDTMFMethod method)
FsRtpSession *self = FS_RTP_SESSION (session);
gboolean ret = FALSE;
+ if (fs_rtp_session_has_disposed_enter (self, NULL))
+ return FALSE;
+
FS_RTP_SESSION_LOCK (self);
ret = fs_rtp_special_sources_stop_telephony_event (
self->priv->extra_sources, method);
FS_RTP_SESSION_UNLOCK (self);
+ fs_rtp_session_has_disposed_exit (self);
return ret;
}
@@ -1558,6 +1627,9 @@ fs_rtp_session_set_send_codec (FsSession *session, FsCodec *send_codec,
FsRtpSession *self = FS_RTP_SESSION (session);
gboolean ret = TRUE;
+ if (fs_rtp_session_has_disposed_enter (self, error))
+ return FALSE;
+
FS_RTP_SESSION_LOCK (self);
if (lookup_codec_association_by_codec_without_config (
@@ -1579,6 +1651,7 @@ fs_rtp_session_set_send_codec (FsSession *session, FsCodec *send_codec,
FS_RTP_SESSION_UNLOCK (self);
+ fs_rtp_session_has_disposed_exit (self);
return ret;
}
@@ -1592,6 +1665,9 @@ fs_rtp_session_set_codec_preferences (FsSession *session,
GList *new_codec_prefs = fs_codec_list_copy (codec_preferences);
gboolean ret;
+ if (fs_rtp_session_has_disposed_enter (self, error))
+ return FALSE;
+
new_codec_prefs =
validate_codecs_configuration (
self->priv->media_type, self->priv->blueprints,
@@ -1626,6 +1702,7 @@ fs_rtp_session_set_codec_preferences (FsSession *session,
GST_WARNING ("Invalid new codec preferences");
}
+ fs_rtp_session_has_disposed_exit (self);
return ret;
}
@@ -1656,6 +1733,9 @@ fs_rtp_session_request_pt_map (FsRtpSession *session, guint pt)
GstCaps *caps = NULL;
CodecAssociation *ca = NULL;
+ if (fs_rtp_session_has_disposed_enter (session, NULL))
+ return NULL;
+
FS_RTP_SESSION_LOCK (session);
ca = lookup_codec_association_by_pt (
@@ -1674,6 +1754,8 @@ fs_rtp_session_request_pt_map (FsRtpSession *session, guint pt)
GST_WARNING ("Could not get caps for payload type %u in session %d",
pt, session->id);
+
+ fs_rtp_session_has_disposed_exit (session);
return caps;
}
@@ -2204,8 +2286,15 @@ _stream_new_remote_codecs (FsRtpStream *stream,
GList *codecs, GError **error, gpointer user_data)
{
FsRtpSession *session = FS_RTP_SESSION_CAST (user_data);
+ gboolean ret;
+
+ if (fs_rtp_session_has_disposed_enter (session, error))
+ return FALSE;
- return fs_rtp_session_update_codecs (session, stream, codecs, error);
+ ret = fs_rtp_session_update_codecs (session, stream, codecs, error);
+
+ fs_rtp_session_has_disposed_exit (session);
+ return ret;
}
@@ -2243,6 +2332,9 @@ fs_rtp_session_new_recv_pad (FsRtpSession *session, GstPad *new_pad,
GError *error = NULL;
gint no_rtcp_timeout;
+ if (fs_rtp_session_has_disposed_enter (session, NULL))
+ return;
+
FS_RTP_SESSION_LOCK (session);
no_rtcp_timeout = session->priv->no_rtcp_timeout;
FS_RTP_SESSION_UNLOCK (session);
@@ -2261,6 +2353,7 @@ fs_rtp_session_new_recv_pad (FsRtpSession *session, GstPad *new_pad,
"No error details returned");
g_clear_error (&error);
+ fs_rtp_session_has_disposed_exit (session);
return;
}
@@ -2347,6 +2440,8 @@ fs_rtp_session_new_recv_pad (FsRtpSession *session, GstPad *new_pad,
if (stream)
g_object_unref (stream);
+
+ fs_rtp_session_has_disposed_exit (session);
}
@@ -3325,6 +3420,12 @@ _send_src_pad_blocked_callback (GstPad *pad, gboolean blocked,
FsCodec *codec_without_config = NULL;
GError *error = NULL;
+ if (fs_rtp_session_has_disposed_enter (self, NULL))
+ {
+ gst_pad_set_blocked_async (pad, FALSE, pad_block_do_nothing, NULL);
+ return;
+ }
+
FS_RTP_SESSION_LOCK (self);
ca = fs_rtp_session_select_send_codec_locked (self, &error);
@@ -3394,6 +3495,7 @@ _send_src_pad_blocked_callback (GstPad *pad, gboolean blocked,
gst_pad_set_blocked_async (pad, FALSE, pad_block_do_nothing, NULL);
+ fs_rtp_session_has_disposed_exit (self);
return;
done_locked:
@@ -3432,6 +3534,9 @@ _substream_blocked (FsRtpSubStream *substream, FsRtpStream *stream,
guint32 ssrc;
guint pt;
+ if (fs_rtp_session_has_disposed_enter (session, NULL))
+ return;
+
FS_RTP_SESSION_LOCK (session);
pt = substream->pt;
@@ -3456,6 +3561,7 @@ _substream_blocked (FsRtpSubStream *substream, FsRtpStream *stream,
}
g_clear_error (&error);
+ fs_rtp_session_has_disposed_exit (session);
}
static void
@@ -3531,6 +3637,9 @@ fs_rtp_session_associate_ssrc_cname (FsRtpSession *session,
FsRtpStream *stream = NULL;
GList *item = NULL;
+ if (fs_rtp_session_has_disposed_enter (session, NULL))
+ return;
+
FS_RTP_SESSION_LOCK (session);
for (item = g_list_first (session->priv->streams);
item;
@@ -3556,10 +3665,11 @@ fs_rtp_session_associate_ssrc_cname (FsRtpSession *session,
{
gchar *str = g_strdup_printf ("There is no particpant with cname %s for"
" ssrc %u", cname, ssrc);
+ FS_RTP_SESSION_UNLOCK (session);
fs_session_emit_error (FS_SESSION (session), FS_ERROR_UNKNOWN_CNAME,
str, str);
g_free (str);
- FS_RTP_SESSION_UNLOCK (session);
+ fs_rtp_session_has_disposed_exit (session);
return;
}
@@ -3569,6 +3679,7 @@ fs_rtp_session_associate_ssrc_cname (FsRtpSession *session,
FS_RTP_SESSION_UNLOCK (session);
fs_rtp_session_associate_free_substreams (session, stream, ssrc);
+ fs_rtp_session_has_disposed_exit (session);
}
static void
@@ -3578,6 +3689,9 @@ _substream_no_rtcp_timedout_cb (FsRtpSubStream *substream,
GError *error = NULL;
FsRtpStream *first_stream = NULL;
+ if (fs_rtp_session_has_disposed_enter (session, NULL))
+ return;
+
FS_RTP_SESSION_LOCK (session);
if (g_list_length (session->priv->streams) != 1)
@@ -3587,6 +3701,7 @@ _substream_no_rtcp_timedout_cb (FsRtpSubStream *substream,
" not associate it.", substream->ssrc, substream->pt,
substream->no_rtcp_timeout);
FS_RTP_SESSION_UNLOCK (session);
+ fs_rtp_session_has_disposed_exit (session);
return;
}
@@ -3595,6 +3710,7 @@ _substream_no_rtcp_timedout_cb (FsRtpSubStream *substream,
GST_WARNING ("Could not find substream %p in the list of free substreams",
substream);
FS_RTP_SESSION_UNLOCK (session);
+ fs_rtp_session_has_disposed_exit (session);
return;
}
@@ -3618,6 +3734,8 @@ _substream_no_rtcp_timedout_cb (FsRtpSubStream *substream,
error ? error->message : "No error message");
g_clear_error (&error);
g_object_unref (first_stream);
+
+ fs_rtp_session_has_disposed_exit (session);
}
/**
@@ -3631,6 +3749,8 @@ void
fs_rtp_session_bye_ssrc (FsRtpSession *session,
guint32 ssrc)
{
+ if (fs_rtp_session_has_disposed_enter (session, NULL))
+ return;
/* First remove it from the known SSRCs */
@@ -3644,6 +3764,8 @@ fs_rtp_session_bye_ssrc (FsRtpSession *session,
* Remove running substreams with that SSRC .. lets also check if they
* come from the right ip/port/etc ??
*/
+
+ fs_rtp_session_has_disposed_exit (session);
}
@@ -3719,6 +3841,9 @@ _send_caps_changed (GstPad *pad, GParamSpec *pspec, FsRtpSession *session)
g_return_if_fail (GST_CAPS_IS_SIMPLE(caps));
+ if (fs_rtp_session_has_disposed_enter (session, NULL))
+ return;
+
FS_RTP_SESSION_LOCK (session);
if (!session->priv->current_send_codec)
@@ -3769,6 +3894,8 @@ _send_caps_changed (GstPad *pad, GParamSpec *pspec, FsRtpSession *session)
out_unlocked:
gst_caps_unref (caps);
+
+ fs_rtp_session_has_disposed_exit (session);
}
static void
@@ -3784,6 +3911,9 @@ _discovery_caps_changed (GstPad *pad, GParamSpec *pspec, FsRtpSession *session)
g_return_if_fail (GST_CAPS_IS_SIMPLE(caps));
+ if (fs_rtp_session_has_disposed_enter (session, NULL))
+ return;
+
FS_RTP_SESSION_LOCK (session);
if (!session->priv->discovery_codec)
@@ -3815,7 +3945,7 @@ _discovery_caps_changed (GstPad *pad, GParamSpec *pspec, FsRtpSession *session)
gst_pad_set_blocked_async (session->priv->send_tee_discovery_pad, TRUE,
_send_sink_pad_blocked_callback, session);
-
+ fs_rtp_session_has_disposed_exit (session);
}
/**
@@ -4053,6 +4183,9 @@ _send_sink_pad_blocked_callback (GstPad *pad, gboolean blocked,
GList *item = NULL;
CodecAssociation *ca = NULL;
+ if (fs_rtp_session_has_disposed_enter (session, NULL))
+ return;
+
FS_RTP_SESSION_LOCK (session);
/* Find out if there is a codec that needs the config to be fetched */
@@ -4094,6 +4227,7 @@ _send_sink_pad_blocked_callback (GstPad *pad, gboolean blocked,
out_unlocked:
gst_pad_set_blocked_async (pad, FALSE, pad_block_do_nothing, NULL);
+ fs_rtp_session_has_disposed_exit (session);
return;
out_locked:
--
1.5.6.5
More information about the farsight-commits
mailing list