From 24a0eec87ba52b35824862ca1150904f48454f39 Mon Sep 17 00:00:00 2001 From: Lorenzo Miniero Date: Thu, 4 Feb 2021 11:53:36 +0100 Subject: [PATCH] Videoroom race condition fixes (see #2509) (#2539) * Fixed missing room references that could cause crashes during race conditions * Fixed rare race condition on publisher join --- plugins/janus_videoroom.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/plugins/janus_videoroom.c b/plugins/janus_videoroom.c index 10b499d96c..6a0976458f 100644 --- a/plugins/janus_videoroom.c +++ b/plugins/janus_videoroom.c @@ -3581,7 +3581,7 @@ static json_t *janus_videoroom_process_synchronous_request(janus_videoroom_sessi g_hash_table_iter_init(&iter, videoroom->participants); while (g_hash_table_iter_next(&iter, NULL, &value)) { janus_videoroom_publisher *p = value; - if(p && p->session) { + if(p && p->session && p->room) { g_clear_pointer(&p->room, janus_videoroom_room_dereference); /* Notify the user we're going to destroy the room... */ int ret = gateway->push_event(p->session->handle, &janus_videoroom_plugin, NULL, destroyed, NULL); @@ -6088,9 +6088,19 @@ static void *janus_videoroom_handler(void *data) { } /* Done */ janus_mutex_lock(&session->mutex); + /* Make sure the session has not been destroyed in the meanwhile */ + if(g_atomic_int_get(&session->destroyed)) { + janus_mutex_unlock(&session->mutex); + janus_mutex_unlock(&publisher->room->mutex); + janus_refcount_decrease(&publisher->room->ref); + janus_videoroom_publisher_destroy(publisher); + JANUS_LOG(LOG_ERR, "Session destroyed, invalidating new publisher\n"); + error_code = JANUS_VIDEOROOM_ERROR_UNKNOWN_ERROR; + g_snprintf(error_cause, 512, "Session destroyed, invalidating new publisher"); + goto error; + } session->participant_type = janus_videoroom_p_type_publisher; session->participant = publisher; - janus_mutex_unlock(&session->mutex); /* Return a list of all available publishers (those with an SDP available, that is) */ json_t *list = json_array(), *attendees = NULL; if(publisher->room->notify_joining) @@ -6101,6 +6111,7 @@ static void *janus_videoroom_handler(void *data) { g_hash_table_insert(publisher->room->participants, string_ids ? (gpointer)g_strdup(publisher->user_id_str) : (gpointer)janus_uint64_dup(publisher->user_id), publisher); + janus_mutex_unlock(&session->mutex); g_hash_table_iter_init(&iter, publisher->room->participants); while (!g_atomic_int_get(&publisher->room->destroyed) && g_hash_table_iter_next(&iter, NULL, &value)) { janus_videoroom_publisher *p = value; @@ -7246,8 +7257,10 @@ static void *janus_videoroom_handler(void *data) { if(p != participant && p->sdp) count++; } + janus_refcount_increase(&videoroom->ref); janus_mutex_unlock(&videoroom->mutex); if(count == videoroom->max_publishers) { + janus_refcount_decrease(&videoroom->ref); participant->audio_active = FALSE; participant->video_active = FALSE; participant->data_active = FALSE; @@ -7257,6 +7270,7 @@ static void *janus_videoroom_handler(void *data) { goto error; } if(videoroom->require_e2ee && !e2ee && !participant->e2ee) { + janus_refcount_decrease(&videoroom->ref); participant->audio_active = FALSE; participant->video_active = FALSE; participant->data_active = FALSE; @@ -7273,6 +7287,7 @@ static void *janus_videoroom_handler(void *data) { char error_str[512]; janus_sdp *offer = janus_sdp_parse(msg_sdp, error_str, sizeof(error_str)); if(offer == NULL) { + janus_refcount_decrease(&videoroom->ref); json_decref(event); JANUS_LOG(LOG_ERR, "Error parsing offer: %s\n", error_str); error_code = JANUS_VIDEOROOM_ERROR_INVALID_SDP; @@ -7580,6 +7595,7 @@ static void *janus_videoroom_handler(void *data) { } s = s->next; } + janus_refcount_decrease(&videoroom->ref); janus_mutex_unlock(&participant->subscribers_mutex); json_decref(update); }