From be38b8c18e6c57ab7acb2fdef6f1a399a8f5d889 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Thu, 21 Feb 2013 16:43:24 +0000 Subject: Re #1623: fixed deadlock between conference mutex and ICE. Scenario: - sound device thread calls put_frame() which gets the conf mutex, and is calling transport sendto() to send RTP packet which requires ICE mutex. - The worker thread finished ICE negotiation and notifies PJSUA-LIB and application while holding ICE group lock, app then do conf_connect() which causes deadlock. This fix defer the callback to a timer. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4363 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/src/pjsua-lib/pjsua_media.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'pjsip') diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index d18703ca..bc979153 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -552,7 +552,8 @@ on_error: } #endif -static void med_tp_timer_cb(void *user_data) +/* Deferred callback to notify ICE init complete */ +static void ice_init_complete_cb(void *user_data) { pjsua_call_media *call_med = (pjsua_call_media*)user_data; @@ -570,7 +571,7 @@ static void med_tp_timer_cb(void *user_data) pjsua_call *call = NULL; pjsip_dialog *dlg = NULL; - if (acquire_call("med_tp_timer_cb", call_med->call->index, + if (acquire_call("ice_init_complete_cb", call_med->call->index, &call, &dlg) != PJ_SUCCESS) { /* Call have been terminated */ @@ -585,6 +586,26 @@ static void med_tp_timer_cb(void *user_data) } } +/* Deferred callback to notify ICE negotiation failure */ +static void ice_failed_nego_cb(void *user_data) +{ + int call_id = (int)(long)user_data; + pjsua_call *call = NULL; + pjsip_dialog *dlg = NULL; + + if (acquire_call("ice_failed_nego_cb", call_id, + &call, &dlg) != PJ_SUCCESS) + { + /* Call have been terminated */ + return; + } + + pjsua_var.ua_cfg.cb.on_call_media_state(call_id); + + if (dlg) + pjsip_dlg_dec_lock(dlg); + +} /* This callback is called when ICE negotiation completes */ static void on_ice_complete(pjmedia_transport *tp, @@ -602,7 +623,7 @@ static void on_ice_complete(pjmedia_transport *tp, switch (op) { case PJ_ICE_STRANS_OP_INIT: call_med->tp_result = result; - pjsua_schedule_timer2(&med_tp_timer_cb, call_med, 1); + pjsua_schedule_timer2(&ice_init_complete_cb, call_med, 1); break; case PJ_ICE_STRANS_OP_NEGOTIATION: if (result == PJ_SUCCESS) { @@ -615,7 +636,9 @@ static void on_ice_complete(pjmedia_transport *tp, call_med->state = PJSUA_CALL_MEDIA_ERROR; call_med->dir = PJMEDIA_DIR_NONE; if (call && pjsua_var.ua_cfg.cb.on_call_media_state) { - pjsua_var.ua_cfg.cb.on_call_media_state(call->index); + /* Defer the callback to a timer */ + pjsua_schedule_timer2(&ice_failed_nego_cb, + (void*)(long)call->index, 1); } } /* Check if default ICE transport address is changed */ -- cgit v1.2.3