Fixed ticket #351: Possible deadlock in pjsua-api presence subscription (thanks Paul Levin)
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1401 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjsip/src/pjsua-lib/pjsua_pres.c b/pjsip/src/pjsua-lib/pjsua_pres.c
index 89f2bad..bc650e5 100644
--- a/pjsip/src/pjsua-lib/pjsua_pres.c
+++ b/pjsip/src/pjsua-lib/pjsua_pres.c
@@ -23,7 +23,7 @@
#define THIS_FILE "pjsua_pres.c"
#ifndef PJSUA_PRES_TIMER
-# define PJSUA_PRES_TIMER 120
+# define PJSUA_PRES_TIMER 2
#endif
@@ -70,7 +70,6 @@
PJSUA_UNLOCK();
return PJ_SUCCESS;
-
}
@@ -207,10 +206,10 @@
pjsua_var.buddy_cnt++;
- pjsua_buddy_subscribe_pres(index, cfg->subscribe);
-
PJSUA_UNLOCK();
+ pjsua_buddy_subscribe_pres(index, cfg->subscribe);
+
return PJ_SUCCESS;
}
@@ -224,16 +223,15 @@
buddy_id<(int)PJ_ARRAY_SIZE(pjsua_var.buddy),
PJ_EINVAL);
- PJSUA_LOCK();
-
if (pjsua_var.buddy[buddy_id].uri.slen == 0) {
- PJSUA_UNLOCK();
return PJ_SUCCESS;
}
/* Unsubscribe presence */
pjsua_buddy_subscribe_pres(buddy_id, PJ_FALSE);
+ PJSUA_LOCK();
+
/* Remove buddy */
pjsua_var.buddy[buddy_id].uri.slen = 0;
pjsua_var.buddy_cnt--;
@@ -262,10 +260,11 @@
buddy = &pjsua_var.buddy[buddy_id];
buddy->monitor = subscribe;
- pjsua_pres_refresh();
PJSUA_UNLOCK();
+ pjsua_pres_refresh();
+
return PJ_SUCCESS;
}
@@ -1014,7 +1013,6 @@
int acc_id;
pjsua_acc *acc;
pj_str_t contact;
- pjsip_dialog *dlg;
pjsip_tx_data *tdata;
pj_status_t status;
@@ -1039,20 +1037,20 @@
&acc->cfg.id,
&contact,
&buddy->uri,
- NULL, &dlg);
+ NULL, &buddy->dlg);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to create dialog",
status);
return;
}
- status = pjsip_pres_create_uac( dlg, &pres_callback,
+ status = pjsip_pres_create_uac( buddy->dlg, &pres_callback,
PJSIP_EVSUB_NO_EVENT_ID, &buddy->sub);
if (status != PJ_SUCCESS) {
pjsua_var.buddy[index].sub = NULL;
pjsua_perror(THIS_FILE, "Unable to create presence client",
status);
- pjsip_dlg_terminate(dlg);
+ pjsip_dlg_terminate(buddy->dlg);
return;
}
@@ -1063,17 +1061,17 @@
pjsip_tpselector tp_sel;
pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel);
- pjsip_dlg_set_transport(dlg, &tp_sel);
+ pjsip_dlg_set_transport(buddy->dlg, &tp_sel);
}
/* Set route-set */
if (!pj_list_empty(&acc->route_set)) {
- pjsip_dlg_set_route_set(dlg, &acc->route_set);
+ pjsip_dlg_set_route_set(buddy->dlg, &acc->route_set);
}
/* Set credentials */
if (acc->cred_cnt) {
- pjsip_auth_clt_set_credentials( &dlg->auth_sess,
+ pjsip_auth_clt_set_credentials( &buddy->dlg->auth_sess,
acc->cred_cnt, acc->cred);
}
@@ -1137,11 +1135,33 @@
}
+/* Lock all buddies */
+#define LOCK_BUDDIES unsigned cnt_ = 0; \
+ pjsip_dialog *dlg_list_[PJSUA_MAX_BUDDIES]; \
+ unsigned i_; \
+ for (i_=0; i_<PJ_ARRAY_SIZE(pjsua_var.buddy);++i_) { \
+ if (pjsua_var.buddy[i_].sub) { \
+ dlg_list_[cnt_++] = pjsua_var.buddy[i_].dlg; \
+ pjsip_dlg_inc_lock(pjsua_var.buddy[i_].dlg); \
+ } \
+ } \
+ PJSUA_LOCK();
+
+/* Unlock all buddies */
+#define UNLOCK_BUDDIES PJSUA_UNLOCK(); \
+ for (i_=0; i_<cnt_; ++i_) { \
+ pjsip_dlg_dec_lock(dlg_list_[i_]); \
+ }
+
+
+
/* It does what it says.. */
static void refresh_client_subscriptions(void)
{
unsigned i;
+ LOCK_BUDDIES;
+
for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) {
if (!pjsua_var.buddy[i].uri.slen)
@@ -1155,6 +1175,8 @@
}
}
+
+ UNLOCK_BUDDIES;
}
/* Timer callback to re-create client subscription */
@@ -1163,17 +1185,13 @@
{
pj_time_val delay = { PJSUA_PRES_TIMER, 0 };
- PJ_UNUSED_ARG(th);
-
- PJSUA_LOCK();
-
entry->id = PJ_FALSE;
refresh_client_subscriptions();
pjsip_endpt_schedule_timer(pjsua_var.endpt, entry, &delay);
entry->id = PJ_TRUE;
- PJSUA_UNLOCK();
+ PJ_UNUSED_ARG(th);
}