[farsight2/master] Make the session inside a stream dispose-safe
Olivier Crête
olivier.crete at collabora.co.uk
Wed Jan 7 17:04:16 PST 2009
- Protect it with its own mutex
- Take a ref when using it
- Unref afterwards
- Remove now useless disposed variable
---
gst/fsrtpconference/fs-rtp-stream.c | 160 ++++++++++++++++++++++++++---------
1 files changed, 118 insertions(+), 42 deletions(-)
diff --git a/gst/fsrtpconference/fs-rtp-stream.c b/gst/fsrtpconference/fs-rtp-stream.c
index aa02654..a4eed8a 100644
--- a/gst/fsrtpconference/fs-rtp-stream.c
+++ b/gst/fsrtpconference/fs-rtp-stream.c
@@ -75,7 +75,7 @@ struct _FsRtpStreamPrivate
stream_known_source_packet_receive_cb known_source_packet_received_cb;
gpointer user_data_for_cb;
- gboolean disposed;
+ GMutex *mutex;
};
@@ -194,61 +194,77 @@ fs_rtp_stream_init (FsRtpStream *self)
/* member init */
self->priv = FS_RTP_STREAM_GET_PRIVATE (self);
- self->priv->disposed = FALSE;
self->priv->session = NULL;
self->participant = NULL;
self->priv->stream_transmitter = NULL;
+ self->priv->mutex = g_mutex_new ();
+
self->priv->direction = FS_DIRECTION_NONE;
}
+static FsRtpSession *
+fs_rtp_stream_get_session (FsRtpStream *self, GError **error)
+{
+ FsRtpSession *session;
+
+ g_mutex_lock (self->priv->mutex);
+ session = self->priv->session;
+ if (session)
+ g_object_ref (session);
+ g_mutex_unlock (self->priv->mutex);
+
+ if (!session)
+ g_set_error (error, FS_ERROR, FS_ERROR_DISPOSED,
+ "Called function after stream has been disposed");
+
+ return session;
+}
+
static void
fs_rtp_stream_dispose (GObject *object)
{
FsRtpStream *self = FS_RTP_STREAM (object);
FsStreamTransmitter *st;
FsRtpParticipant *participant;
- FsRtpSession *session;
+ FsRtpSession *session = fs_rtp_stream_get_session (self, NULL);
- FS_RTP_SESSION_LOCK (self->priv->session);
-
- if (self->priv->disposed) {
- /* If dispose did already run, return. */
- FS_RTP_SESSION_UNLOCK (self->priv->session);
+ if (!session)
return;
- }
- /* Make sure dispose does not run twice. */
- self->priv->disposed = TRUE;
+ g_mutex_lock (self->priv->mutex);
+ self->priv->session = NULL;
+ g_mutex_unlock (self->priv->mutex);
+
+ FS_RTP_SESSION_LOCK (session);
+ participant = self->participant;
+ self->participant = NULL;
st = self->priv->stream_transmitter;
self->priv->stream_transmitter = NULL;
if (st)
{
- FS_RTP_SESSION_UNLOCK (self->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
fs_stream_transmitter_stop (st);
g_object_unref (st);
- FS_RTP_SESSION_LOCK (self->priv->session);
+ FS_RTP_SESSION_LOCK (session);
}
while (self->substreams)
{
FsRtpSubStream *substream = self->substreams->data;
self->substreams = g_list_remove (self->substreams, substream);
- FS_RTP_SESSION_UNLOCK (self->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
g_object_unref (substream);
- FS_RTP_SESSION_LOCK (self->priv->session);
+ FS_RTP_SESSION_LOCK (session);
}
- participant = self->participant;
- self->participant = NULL;
- session = self->priv->session;
- self->priv->session = NULL;
FS_RTP_SESSION_UNLOCK (session);
g_object_unref (participant);
g_object_unref (session);
+ g_object_unref (session);
parent_class->dispose (object);
}
@@ -261,6 +277,8 @@ fs_rtp_stream_finalize (GObject *object)
fs_codec_list_destroy (self->remote_codecs);
fs_codec_list_destroy (self->negotiated_codecs);
+ g_mutex_free (self->priv->mutex);
+
parent_class->finalize (object);
}
@@ -284,20 +302,24 @@ fs_rtp_stream_get_property (GObject *object,
GParamSpec *pspec)
{
FsRtpStream *self = FS_RTP_STREAM (object);
+ FsRtpSession *session = fs_rtp_stream_get_session (self, NULL);
+
+ if (!session)
+ return;
switch (prop_id) {
case PROP_REMOTE_CODECS:
- FS_RTP_SESSION_LOCK (self->priv->session);
+ FS_RTP_SESSION_LOCK (session);
g_value_set_boxed (value, self->remote_codecs);
- FS_RTP_SESSION_UNLOCK (self->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
break;
case PROP_NEGOTIATED_CODECS:
- FS_RTP_SESSION_LOCK (self->priv->session);
+ FS_RTP_SESSION_LOCK (session);
g_value_set_boxed (value, self->negotiated_codecs);
- FS_RTP_SESSION_UNLOCK (self->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
break;
case PROP_SESSION:
- g_value_set_object (value, self->priv->session);
+ g_value_set_object (value, session);
break;
case PROP_PARTICIPANT:
g_value_set_object (value, self->participant);
@@ -310,7 +332,7 @@ fs_rtp_stream_get_property (GObject *object,
GList *codeclist = NULL;
GList *substream_item;
- FS_RTP_SESSION_LOCK (self->priv->session);
+ FS_RTP_SESSION_LOCK (session);
for (substream_item = g_list_first (self->substreams);
substream_item;
substream_item = g_list_next (substream_item))
@@ -326,13 +348,15 @@ fs_rtp_stream_get_property (GObject *object,
}
g_value_take_boxed (value, codeclist);
- FS_RTP_SESSION_UNLOCK (self->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
+
+ g_object_unref (session);
}
static void
@@ -342,8 +366,12 @@ fs_rtp_stream_set_property (GObject *object,
GParamSpec *pspec)
{
FsRtpStream *self = FS_RTP_STREAM (object);
+ FsRtpSession *session = fs_rtp_stream_get_session (self, NULL);
GList *item;
+ if (!session)
+ return;
+
switch (prop_id) {
case PROP_SESSION:
self->priv->session = FS_RTP_SESSION (g_value_dup_object (value));
@@ -360,19 +388,21 @@ fs_rtp_stream_set_property (GObject *object,
if (self->priv->stream_transmitter)
g_object_set (self->priv->stream_transmitter, "sending",
self->priv->direction & FS_DIRECTION_SEND, NULL);
- FS_RTP_SESSION_LOCK (self->priv->session);
+ FS_RTP_SESSION_LOCK (session);
for (item = g_list_first (self->substreams);
item;
item = g_list_next (item))
g_object_set (G_OBJECT (item->data),
"receiving", ((self->priv->direction & FS_DIRECTION_RECV) != 0),
NULL);
- FS_RTP_SESSION_UNLOCK (self->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
+
+ g_object_unref (session);
}
static void
@@ -484,6 +514,10 @@ fs_rtp_stream_set_remote_codecs (FsStream *stream,
FsRtpStream *self = FS_RTP_STREAM (stream);
GList *item = NULL;
FsMediaType media_type;
+ FsRtpSession *session = fs_rtp_stream_get_session (self, error);
+
+ if (!session)
+ return FALSE;
if (remote_codecs == NULL) {
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
@@ -491,7 +525,7 @@ fs_rtp_stream_set_remote_codecs (FsStream *stream,
goto error;
}
- g_object_get (self->priv->session, "media-type", &media_type, NULL);
+ g_object_get (session, "media-type", &media_type, NULL);
for (item = g_list_first (remote_codecs); item; item = g_list_next (item))
{
@@ -528,18 +562,21 @@ fs_rtp_stream_set_remote_codecs (FsStream *stream,
if (self->priv->new_remote_codecs_cb (self, remote_codecs, error,
self->priv->user_data_for_cb))
{
- FS_RTP_SESSION_LOCK (self->priv->session);
+ FS_RTP_SESSION_LOCK (session);
if (self->remote_codecs)
fs_codec_list_destroy (self->remote_codecs);
self->remote_codecs = fs_codec_list_copy (remote_codecs);
- FS_RTP_SESSION_UNLOCK (self->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
} else {
goto error;
}
+ g_object_unref (session);
return TRUE;
error:
+
+ g_object_unref (session);
return FALSE;
}
@@ -606,8 +643,12 @@ _local_candidates_prepared (FsStreamTransmitter *stream_transmitter,
{
FsRtpStream *self = FS_RTP_STREAM (user_data);
GstElement *conf = NULL;
+ FsRtpSession *session = fs_rtp_stream_get_session (self, NULL);
- g_object_get (self->priv->session, "conference", &conf, NULL);
+ if (!session)
+ return;
+
+ g_object_get (session, "conference", &conf, NULL);
gst_element_post_message (conf,
gst_message_new_element (GST_OBJECT (conf),
@@ -616,6 +657,7 @@ _local_candidates_prepared (FsStreamTransmitter *stream_transmitter,
NULL)));
gst_object_unref (conf);
+ g_object_unref (session);
}
@@ -627,9 +669,13 @@ _new_active_candidate_pair (
gpointer user_data)
{
FsRtpStream *self = FS_RTP_STREAM (user_data);
+ FsRtpSession *session = fs_rtp_stream_get_session (self, NULL);
GstElement *conf = NULL;
- g_object_get (self->priv->session, "conference", &conf, NULL);
+ if (!session)
+ return;
+
+ g_object_get (session, "conference", &conf, NULL);
gst_element_post_message (conf,
gst_message_new_element (GST_OBJECT (conf),
@@ -640,6 +686,7 @@ _new_active_candidate_pair (
NULL)));
gst_object_unref (conf);
+ g_object_unref (session);
}
@@ -650,9 +697,13 @@ _new_local_candidate (
gpointer user_data)
{
FsRtpStream *self = FS_RTP_STREAM (user_data);
+ FsRtpSession *session = fs_rtp_stream_get_session (self, NULL);
GstElement *conf = NULL;
- g_object_get (self->priv->session, "conference", &conf, NULL);
+ if (!session)
+ return;
+
+ g_object_get (session, "conference", &conf, NULL);
gst_element_post_message (conf,
gst_message_new_element (GST_OBJECT (conf),
@@ -662,6 +713,7 @@ _new_local_candidate (
NULL)));
gst_object_unref (conf);
+ g_object_unref (session);
}
static void
@@ -694,9 +746,13 @@ _state_changed (FsStreamTransmitter *stream_transmitter,
gpointer user_data)
{
FsRtpStream *self = FS_RTP_STREAM (user_data);
+ FsRtpSession *session = fs_rtp_stream_get_session (self, NULL);
GstElement *conf = NULL;
- g_object_get (self->priv->session, "conference", &conf, NULL);
+ if (!session)
+ return;
+
+ g_object_get (session, "conference", &conf, NULL);
gst_element_post_message (conf,
gst_message_new_element (GST_OBJECT (conf),
@@ -707,6 +763,7 @@ _state_changed (FsStreamTransmitter *stream_transmitter,
NULL)));
gst_object_unref (conf);
+ g_object_unref (session);
if (component == 1 && state == FS_STREAM_STATE_FAILED)
fs_stream_emit_error (FS_STREAM (self), FS_ERROR_CONNECTION_FAILED,
@@ -753,6 +810,10 @@ fs_rtp_stream_add_substream_unlock (FsRtpStream *stream,
GError **error)
{
gboolean ret = TRUE;
+ FsRtpSession *session = fs_rtp_stream_get_session (stream, error);
+
+ if (!session)
+ return FALSE;
stream->substreams = g_list_prepend (stream->substreams,
substream);
@@ -772,7 +833,9 @@ fs_rtp_stream_add_substream_unlock (FsRtpStream *stream,
if (substream->codec)
ret = fs_rtp_sub_stream_add_output_ghostpad_unlock (substream, error);
else
- FS_RTP_SESSION_UNLOCK (stream->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
+
+ g_object_unref (session);
return ret;
}
@@ -793,12 +856,17 @@ _substream_codec_changed (FsRtpSubStream *substream,
{
GList *substream_item = NULL;
GList *codeclist = NULL;
+ FsRtpSession *session = fs_rtp_stream_get_session (stream, NULL);
- FS_RTP_SESSION_LOCK (stream->priv->session);
+ if (!session)
+ return;
+
+ FS_RTP_SESSION_LOCK (session);
if (!substream->codec)
{
- FS_RTP_SESSION_UNLOCK (stream->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
+ g_object_unref (session);
return;
}
@@ -824,7 +892,7 @@ _substream_codec_changed (FsRtpSubStream *substream,
}
}
- FS_RTP_SESSION_UNLOCK (stream->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
if (substream_item == NULL)
{
@@ -832,7 +900,7 @@ _substream_codec_changed (FsRtpSubStream *substream,
g_object_notify (G_OBJECT (stream), "current-recv-codecs");
- g_object_get (stream->priv->session, "conference", &conf, NULL);
+ g_object_get (session, "conference", &conf, NULL);
gst_element_post_message (conf,
gst_message_new_element (GST_OBJECT (conf),
@@ -845,6 +913,7 @@ _substream_codec_changed (FsRtpSubStream *substream,
}
fs_codec_list_destroy (codeclist);
+ g_object_unref (session);
}
/**
@@ -863,10 +932,15 @@ void
fs_rtp_stream_set_negotiated_codecs_unlock (FsRtpStream *stream,
GList *codecs)
{
+ FsRtpSession *session = fs_rtp_stream_get_session (stream, NULL);
+
+ if (!session)
+ return;
+
if (fs_codec_list_are_equal (stream->negotiated_codecs, codecs))
{
fs_codec_list_destroy (codecs);
- FS_RTP_SESSION_UNLOCK (stream->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
return;
}
@@ -875,7 +949,9 @@ fs_rtp_stream_set_negotiated_codecs_unlock (FsRtpStream *stream,
stream->negotiated_codecs = codecs;
- FS_RTP_SESSION_UNLOCK (stream->priv->session);
+ FS_RTP_SESSION_UNLOCK (session);
g_object_notify (G_OBJECT (stream), "negotiated-codecs");
+
+ g_object_unref (session);
}
--
1.5.6.5
More information about the farsight-commits
mailing list