diff --git a/daemon/call.c b/daemon/call.c index bca465af7..067f685f5 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -3660,7 +3660,6 @@ static void __call_cleanup(struct call *c) { void call_destroy(struct call *c) { struct packet_stream *ps=0; GList *l; - int ret; struct call_monologue *ml; struct call_media *md; GList *k, *o; @@ -3671,15 +3670,20 @@ void call_destroy(struct call *c) { } rwlock_lock_w(&rtpe_callhash_lock); - ret = (g_hash_table_lookup(rtpe_callhash, &c->callid) == c); - if (ret) { - g_hash_table_remove(rtpe_callhash, &c->callid); - RTPE_GAUGE_DEC(total_sessions); + struct call *call_ht = NULL; + g_hash_table_steal_extended(rtpe_callhash, &c->callid, NULL, (void **) &call_ht); + if (call_ht) { + if (call_ht != c) { + g_hash_table_insert(rtpe_callhash, &call_ht->callid, call_ht); + call_ht = NULL; + } + else + RTPE_GAUGE_DEC(total_sessions); } rwlock_unlock_w(&rtpe_callhash_lock); // if call not found in callhash => previously deleted - if (!ret) + if (!call_ht) return; obj_put(c); diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index d0d628ed3..ce3d4a919 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1978,16 +1978,16 @@ static void dequeue_sdp_fragments(struct call_monologue *dialogue[2]) { k.call_id = dialogue[0]->call->callid; k.from_tag = dialogue[0]->tag; - mutex_lock(&sdp_fragments_lock); - GQueue *frags = g_hash_table_lookup(sdp_fragments, &k); - if (!frags) { - mutex_unlock(&sdp_fragments_lock); - return; - } + GQueue *frags = NULL; - g_hash_table_remove(sdp_fragments, &k); - // we own the queue now - mutex_unlock(&sdp_fragments_lock); + { + LOCK(&sdp_fragments_lock); + g_hash_table_steal_extended(sdp_fragments, &k, NULL, (void **) &frags); + if (!frags) + return; + + // we own the queue now + } struct sdp_fragment *frag; while ((frag = g_queue_pop_head(frags))) { diff --git a/daemon/janus.c b/daemon/janus.c index 129b3f705..c5152ee33 100644 --- a/daemon/janus.c +++ b/daemon/janus.c @@ -265,15 +265,13 @@ static const char *janus_videoroom_destroy(struct janus_session *session, struct janus_room *room = NULL; if (room_id) - room = g_hash_table_lookup(janus_rooms, &room_id); + g_hash_table_steal_extended(janus_rooms, &room_id, NULL, (void **) &room); *retcode = 426; if (!room) return "No such room"; ilog(LOG_INFO, "Destroying videoroom with ID %" PRIu64, room_id); - g_hash_table_remove(janus_rooms, &room_id); - struct call *call = call_get(&room->call_id); // XXX if call is destroyed separately, room persist -> room should be destroyed too if (call) { @@ -1342,16 +1340,20 @@ const char *janus_detach(struct websocket_message *wm, JsonReader *reader, JsonB LOCK(&janus_lock); - struct janus_handle *handle = g_hash_table_lookup(janus_handles, &handle_id); + struct janus_handle *handle = NULL; + g_hash_table_steal_extended(janus_handles, &handle_id, NULL, (void **) &handle); *retcode = 463; - if (!handle || handle->session != session) + if (!handle) return "Could not detach handle from plugin"; + if (handle->session != session) { + g_hash_table_insert(janus_handles, &handle->id, handle); + return "Invalid session/handle association"; + } room_id = handle->room; // destroy handle - g_hash_table_remove(janus_handles, &handle_id); obj_put(session); g_slice_free1(sizeof(*handle), handle);