summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2013-02-21 16:43:24 +0000
committerBenny Prijono <bennylp@teluu.com>2013-02-21 16:43:24 +0000
commitbe38b8c18e6c57ab7acb2fdef6f1a399a8f5d889 (patch)
tree54cefc46436bd93c853d35257f0aa59ca594af24
parent57ea4f8e4354e9bb5ac0d4ae11d06f194b78bf01 (diff)
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
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c31
1 files changed, 27 insertions, 4 deletions
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 */