[Pkg-voip-commits] [janus] 78/163: Better management of session timeouts and destruction (see #986)

Jonas Smedegaard dr at jones.dk
Sat Oct 28 01:22:12 UTC 2017


This is an automated email from the git hooks/post-receive script.

js pushed a commit to annotated tag debian/0.2.5-1
in repository janus.

commit 5ffcf9a8e999f26555e823d81ab8f20cd1c427d2
Author: Lorenzo Miniero <lminiero at gmail.com>
Date:   Fri Sep 1 19:31:57 2017 +0200

    Better management of session timeouts and destruction (see #986)
---
 janus.c | 117 ++++++++++++++++++++++++++++++----------------------------------
 janus.h |   4 +--
 2 files changed, 56 insertions(+), 65 deletions(-)

diff --git a/janus.c b/janus.c
index d2e3c90..fe1a7f7 100644
--- a/janus.c
+++ b/janus.c
@@ -404,16 +404,52 @@ static GMainContext *sessions_watchdog_context = NULL;
 static gboolean janus_cleanup_session(gpointer user_data) {
 	janus_session *session = (janus_session *) user_data;
 
-	JANUS_LOG(LOG_DBG, "Cleaning up session %"SCNu64"...\n", session->session_id);
+	JANUS_LOG(LOG_INFO, "Cleaning up session %"SCNu64"...\n", session->session_id);
 	janus_session_destroy(session->session_id);
 
 	return G_SOURCE_REMOVE;
 }
 
+static void janus_session_schedule_destruction(janus_session *session,
+		gboolean lock_sessions, gboolean remove_key, gboolean notify_transport) {
+	if(session == NULL || !g_atomic_int_compare_and_exchange(&session->destroy, 0, 1))
+		return;
+	if(lock_sessions)
+		janus_mutex_lock(&sessions_mutex);
+	/* Schedule the session for deletion */
+	janus_mutex_lock(&session->mutex);
+	/* Remove all handles */
+	if(session->ice_handles != NULL && g_hash_table_size(session->ice_handles) > 0) {
+		GHashTableIter iter;
+		gpointer value;
+		g_hash_table_iter_init(&iter, session->ice_handles);
+		while(g_hash_table_iter_next(&iter, NULL, &value)) {
+			janus_ice_handle *h = value;
+			if(!h || g_atomic_int_get(&stop)) {
+				continue;
+			}
+			janus_ice_handle_destroy(session, h->handle_id);
+			g_hash_table_iter_remove(&iter);
+		}
+	}
+	janus_mutex_unlock(&session->mutex);
+	if(remove_key)
+		g_hash_table_remove(sessions, &session->session_id);
+	g_hash_table_replace(old_sessions, janus_uint64_dup(session->session_id), session);
+	GSource *timeout_source = g_timeout_source_new_seconds(3);
+	g_source_set_callback(timeout_source, janus_cleanup_session, session, NULL);
+	g_source_attach(timeout_source, sessions_watchdog_context);
+	g_source_unref(timeout_source);
+	if(lock_sessions)
+		janus_mutex_unlock(&sessions_mutex);
+	/* Notify the source that the session has been destroyed */
+	if(notify_transport && session->source && session->source->transport)
+		session->source->transport->session_over(session->source->instance, session->session_id, FALSE);
+}
+
 static gboolean janus_check_sessions(gpointer user_data) {
 	if(session_timeout < 1)		/* Session timeouts are disabled */
 		return G_SOURCE_CONTINUE;
-	GMainContext *watchdog_context = (GMainContext *) user_data;
 	janus_mutex_lock(&sessions_mutex);
 	if(sessions && g_hash_table_size(sessions) > 0) {
 		GHashTableIter iter;
@@ -421,30 +457,15 @@ static gboolean janus_check_sessions(gpointer user_data) {
 		g_hash_table_iter_init(&iter, sessions);
 		while (g_hash_table_iter_next(&iter, NULL, &value)) {
 			janus_session *session = (janus_session *) value;
-			if (!session || session->destroy) {
+			if (!session || g_atomic_int_get(&session->destroy)) {
 				continue;
 			}
 			gint64 now = janus_get_monotonic_time();
-			if (now - session->last_activity >= (gint64)session_timeout * G_USEC_PER_SEC && !session->timeout) {
+			if (now - session->last_activity >= (gint64)session_timeout * G_USEC_PER_SEC &&
+					!g_atomic_int_compare_and_exchange(&session->timeout, 0, 1)) {
 				JANUS_LOG(LOG_INFO, "Timeout expired for session %"SCNu64"...\n", session->session_id);
 				/* Mark the session as over, we'll deal with it later */
-				janus_mutex_lock(&session->mutex);
-				session->timeout = 1;
-				/* Remove all handles */
-				if(session->ice_handles != NULL && g_hash_table_size(session->ice_handles) > 0) {
-					GHashTableIter iter;
-					gpointer value;
-					g_hash_table_iter_init(&iter, session->ice_handles);
-					while(g_hash_table_iter_next(&iter, NULL, &value)) {
-						janus_ice_handle *h = value;
-						if(!h || g_atomic_int_get(&stop)) {
-							continue;
-						}
-						janus_ice_handle_destroy(session, h->handle_id);
-						g_hash_table_iter_remove(&iter);
-					}
-				}
-				janus_mutex_unlock(&session->mutex);
+				janus_session_schedule_destruction(session, FALSE, FALSE, FALSE);
 				/* Notify the transport */
 				if(session->source) {
 					json_t *event = json_object();
@@ -461,13 +482,7 @@ static gboolean janus_check_sessions(gpointer user_data) {
 
 				/* FIXME Is this safe? apparently it causes hash table errors on the console */
 				g_hash_table_iter_remove(&iter);
-				g_hash_table_insert(old_sessions, janus_uint64_dup(session->session_id), session);
-
-				/* Schedule the session for deletion */
-				GSource *timeout_source = g_timeout_source_new_seconds(3);
-				g_source_set_callback(timeout_source, janus_cleanup_session, session, NULL);
-				g_source_attach(timeout_source, watchdog_context);
-				g_source_unref(timeout_source);
+				g_hash_table_replace(old_sessions, janus_uint64_dup(session->session_id), session);
 			}
 		}
 	}
@@ -511,8 +526,8 @@ janus_session *janus_session_create(guint64 session_id) {
 	}
 	session->session_id = session_id;
 	session->source = NULL;
-	session->destroy = 0;
-	session->timeout = 0;
+	g_atomic_int_set(&session->destroy, 0);
+	g_atomic_int_set(&session->timeout, 0);
 	session->last_activity = janus_get_monotonic_time();
 	janus_mutex_init(&session->mutex);
 	janus_mutex_lock(&sessions_mutex);
@@ -531,12 +546,13 @@ janus_session *janus_session_find(guint64 session_id) {
 janus_session *janus_session_find_destroyed(guint64 session_id) {
 	janus_mutex_lock(&sessions_mutex);
 	janus_session *session = g_hash_table_lookup(old_sessions, &session_id);
+	g_hash_table_remove(old_sessions, &session_id);
 	janus_mutex_unlock(&sessions_mutex);
 	return session;
 }
 
 void janus_session_notify_event(janus_session *session, json_t *event) {
-	if(session != NULL && !session->destroy && session->source != NULL && session->source->transport != NULL) {
+	if(session != NULL && !g_atomic_int_get(&session->destroy) && session->source != NULL && session->source->transport != NULL) {
 		/* Send this to the transport client */
 		JANUS_LOG(LOG_HUGE, "Sending event to %s (%p)\n", session->source->transport->get_package(), session->source->instance);
 		session->source->transport->send_message(session->source->instance, NULL, FALSE, event);
@@ -868,35 +884,8 @@ int janus_process_incoming_request(janus_request *request) {
 			ret = janus_process_error(request, session_id, transaction_text, JANUS_ERROR_INVALID_REQUEST_PATH, "Unhandled request '%s' at this path", message_text);
 			goto jsondone;
 		}
-		janus_mutex_lock(&sessions_mutex);
-		/* Schedule the session for deletion */
-		janus_mutex_lock(&session->mutex);
-		session->destroy = 1;
-		/* Remove all handles */
-		if(session->ice_handles != NULL && g_hash_table_size(session->ice_handles) > 0) {
-			GHashTableIter iter;
-			gpointer value;
-			g_hash_table_iter_init(&iter, session->ice_handles);
-			while(g_hash_table_iter_next(&iter, NULL, &value)) {
-				janus_ice_handle *h = value;
-				if(!h || g_atomic_int_get(&stop)) {
-					continue;
-				}
-				janus_ice_handle_destroy(session, h->handle_id);
-				g_hash_table_iter_remove(&iter);
-			}
-		}
-		janus_mutex_unlock(&session->mutex);
-		g_hash_table_remove(sessions, &session->session_id);
-		g_hash_table_insert(old_sessions, janus_uint64_dup(session->session_id), session);
-		GSource *timeout_source = g_timeout_source_new_seconds(3);
-		g_source_set_callback(timeout_source, janus_cleanup_session, session, NULL);
-		g_source_attach(timeout_source, sessions_watchdog_context);
-		g_source_unref(timeout_source);
-		janus_mutex_unlock(&sessions_mutex);
-		/* Notify the source that the session has been destroyed */
-		if(session->source && session->source->transport)
-			session->source->transport->session_over(session->source->instance, session->session_id, FALSE);
+		/* Mark the session as destroyed */
+		janus_session_schedule_destruction(session, TRUE, TRUE, TRUE);
 
 		/* Prepare JSON reply */
 		json_t *reply = json_object();
@@ -2600,11 +2589,13 @@ void janus_transport_gone(janus_transport *plugin, void *transport) {
 		g_hash_table_iter_init(&iter, sessions);
 		while(g_hash_table_iter_next(&iter, NULL, &value)) {
 			janus_session *session = (janus_session *) value;
-			if(!session || session->destroy || session->timeout || session->last_activity == 0)
+			if(!session || g_atomic_int_get(&session->destroy) || g_atomic_int_get(&session->timeout) || session->last_activity == 0)
 				continue;
 			if(session->source && session->source->instance == transport) {
 				JANUS_LOG(LOG_VERB, "  -- Marking Session %"SCNu64" as over\n", session->session_id);
-				session->last_activity = 0;	/* This will trigger a timeout */
+				/* Mark the session as destroyed */
+				janus_session_schedule_destruction(session, FALSE, FALSE, FALSE);
+				g_hash_table_iter_remove(&iter);
 			}
 		}
 	}
@@ -2710,7 +2701,7 @@ int janus_plugin_push_event(janus_plugin_session *plugin_session, janus_plugin *
 	if(!ice_handle || janus_flags_is_set(&ice_handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_STOP))
 		return JANUS_ERROR_SESSION_NOT_FOUND;
 	janus_session *session = ice_handle->session;
-	if(!session || session->destroy)
+	if(!session || g_atomic_int_get(&session->destroy))
 		return JANUS_ERROR_SESSION_NOT_FOUND;
 	/* Make sure this is a JSON object */
 	if(!json_is_object(message)) {
diff --git a/janus.h b/janus.h
index 48b013d..e552adc 100644
--- a/janus.h
+++ b/janus.h
@@ -53,9 +53,9 @@ typedef struct janus_session {
 	/*! \brief Pointer to the request instance (and the transport that originated the session) */
 	janus_request *source;
 	/*! \brief Flag to trigger a lazy session destruction */
-	gint destroy:1;
+	volatile gint destroy;
 	/*! \brief Flag to notify there's been a session timeout */
-	gint timeout:1;
+	volatile gint timeout;
 	/*! \brief Mutex to lock/unlock this session */
 	janus_mutex mutex;
 } janus_session;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-voip/janus.git



More information about the Pkg-voip-commits mailing list