diff options
author | Ognyan Tonchev <ognyan@axis.com> | 2014-07-09 15:01:31 +0200 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2014-07-09 16:16:50 +0200 |
commit | e0bc97e40cdf49de2911038c92275b6181113ba6 (patch) | |
tree | 422b24af7caa6d438a2195f5bd6b4ef771da78cb | |
parent | 5aec4af1b96ef5bddfc02a015e9cec3488c89f4a (diff) |
client: keep ref to client for the session removed handler
This extra ref will be dropped when all client sessions have been
removed. A session is removed when a client sends teardown, closes its
endpoint of the TCP connection or the sessions expires.
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=732226
-rw-r--r-- | gst/rtsp-server/rtsp-client.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index 46da780..e94567c 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -144,6 +144,8 @@ static GstRTSPResult default_params_get (GstRTSPClient * client, GstRTSPContext * ctx); static gchar *default_make_path_from_uri (GstRTSPClient * client, const GstRTSPUrl * uri); +static void client_session_removed (GstRTSPSessionPool * pool, + GstRTSPSession * session, GstRTSPClient * client); G_DEFINE_TYPE (GstRTSPClient, gst_rtsp_client, G_TYPE_OBJECT); @@ -301,7 +303,15 @@ client_watch_session (GstRTSPClient * client, GstRTSPSession * session) /* check if we already know about this session */ if (g_list_find (priv->sessions, session) == NULL) { GST_INFO ("watching session %p", session); + priv->sessions = g_list_prepend (priv->sessions, g_object_ref (session)); + + /* connect removed session handler, it will be disconnected when the last + * session gets removed */ + if (priv->session_removed_id == 0) + priv->session_removed_id = g_signal_connect_data (priv->session_pool, + "session-removed", G_CALLBACK (client_session_removed), + g_object_ref (client), (GClosureNotify) g_object_unref, 0); } g_mutex_unlock (&priv->lock); @@ -322,8 +332,17 @@ client_unwatch_session (GstRTSPClient * client, GstRTSPSession * session, if (link == NULL) return; } + priv->sessions = g_list_delete_link (priv->sessions, link); + /* if this was the last session, disconnect the handler. + * This will also drop the extra client ref */ + if (!priv->sessions) { + g_signal_handler_disconnect (priv->session_pool, + priv->session_removed_id); + priv->session_removed_id = 0; + } + /* unlink all media managed in this session */ gst_rtsp_session_filter (session, filter_session_media, client); @@ -357,12 +376,15 @@ gst_rtsp_client_finalize (GObject * obj) if (priv->watch_context) g_main_context_unref (priv->watch_context); - gst_rtsp_client_session_filter (client, cleanup_session, NULL); + /* all sessions should have been removed by now. We keep a ref to + * the client object for the session removed handler. The ref is + * dropped when the last session is removed from the list. */ + g_assert (priv->sessions == NULL); + g_assert (priv->session_removed_id == 0); if (priv->connection) gst_rtsp_connection_free (priv->connection); if (priv->session_pool) { - g_signal_handler_disconnect (priv->session_pool, priv->session_removed_id); g_object_unref (priv->session_pool); } if (priv->mount_points) @@ -2644,13 +2666,10 @@ gst_rtsp_client_set_session_pool (GstRTSPClient * client, old = priv->session_pool; priv->session_pool = pool; - if (priv->session_removed_id) + if (priv->session_removed_id) { g_signal_handler_disconnect (old, priv->session_removed_id); - if (pool) - priv->session_removed_id = g_signal_connect (pool, "session-removed", - G_CALLBACK (client_session_removed), client); - else priv->session_removed_id = 0; + } g_mutex_unlock (&priv->lock); /* FIXME, should remove all sessions from the old pool for this client */ @@ -3353,6 +3372,8 @@ client_watch_notify (GstRTSPClient * client) priv->watch = NULL; g_main_context_unref (priv->watch_context); priv->watch_context = NULL; + /* remove all sessions and so drop the extra client ref */ + gst_rtsp_client_session_filter (client, cleanup_session, NULL); g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_CLOSED], 0, NULL); g_object_unref (client); } |