From c7085085a7d154608144db2a201d65547f23f520 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Wed, 8 Sep 2021 09:23:16 -0400 Subject: [PATCH] TT#14008 fix lock order between janus_session and websocket_conn Make sure janus_session lock is obtained first and websocket_conn lock second, in order to prevent a possible deadlock. Change-Id: I3db1d5cea0c0295cc10c71edd20c86ce054f520b Warned-by: Coverity --- daemon/janus.c | 2 ++ daemon/websocket.c | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/daemon/janus.c b/daemon/janus.c index c891a4fad..f86aa770c 100644 --- a/daemon/janus.c +++ b/daemon/janus.c @@ -932,6 +932,8 @@ void janus_media_up(struct call_monologue *ml) { g_object_unref(gen); g_object_unref(builder); + // lock order constraint: janus_session lock first, websocket_conn lock second + LOCK(&session->lock); GHashTableIter iter; diff --git a/daemon/websocket.c b/daemon/websocket.c index 77614b2e9..c886f61d9 100644 --- a/daemon/websocket.c +++ b/daemon/websocket.c @@ -573,20 +573,27 @@ static void websocket_conn_cleanup(struct websocket_conn *wc) { while (wc->jobs) cond_wait(&wc->cond, &wc->lock); + // lock order constraint: janus_session lock first, websocket_conn lock second: + // therefore, remove janus_sessions list from wc, then unlock, then iterate the + // list, as janus_detach_websocket locks the session + + GHashTable *janus_sessions = wc->janus_sessions; + wc->janus_sessions = NULL; + + mutex_unlock(&wc->lock); + // detach all Janus sessions - if (wc->janus_sessions) { + if (janus_sessions) { GHashTableIter iter; - g_hash_table_iter_init(&iter, wc->janus_sessions); + g_hash_table_iter_init(&iter, janus_sessions); gpointer key; while (g_hash_table_iter_next(&iter, &key, NULL)) { janus_detach_websocket(key, wc); __obj_put(key); } - g_hash_table_destroy(wc->janus_sessions); - wc->janus_sessions = NULL; + g_hash_table_destroy(janus_sessions); } - mutex_unlock(&wc->lock); assert(wc->messages.length == 0);