From a097c5c02918f7813e107d2365f1cc70055fc551 Mon Sep 17 00:00:00 2001 From: Riza Sulistyo Date: Tue, 30 Aug 2016 08:40:18 +0000 Subject: Re #1959: Add reference counter to pjsip_inv_session to avoid race condition. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5435 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/src/pjsip-ua/sip_inv.c | 95 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 21 deletions(-) (limited to 'pjsip/src/pjsip-ua') diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c index a8882b55..fbc8ebed 100644 --- a/pjsip/src/pjsip-ua/sip_inv.c +++ b/pjsip/src/pjsip-ua/sip_inv.c @@ -194,6 +194,65 @@ static pj_status_t mod_inv_unload(void) return PJ_SUCCESS; } +/* + * Add reference to INVITE session. + */ +PJ_DEF(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv ) +{ + PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL); + + pj_atomic_inc(inv->ref_cnt); + + return PJ_SUCCESS; +} + +static void inv_session_destroy(pjsip_inv_session *inv) +{ + if (inv->last_ack) { + pjsip_tx_data_dec_ref(inv->last_ack); + inv->last_ack = NULL; + } + if (inv->invite_req) { + pjsip_tx_data_dec_ref(inv->invite_req); + inv->invite_req = NULL; + } + if (inv->pending_bye) { + pjsip_tx_data_dec_ref(inv->pending_bye); + inv->pending_bye = NULL; + } + pjsip_100rel_end_session(inv); + pjsip_timer_end_session(inv); + pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod); + + /* Release the flip-flop pools */ + pj_pool_release(inv->pool_prov); + inv->pool_prov = NULL; + pj_pool_release(inv->pool_active); + inv->pool_active = NULL; + + pj_atomic_destroy(inv->ref_cnt); + inv->ref_cnt = NULL; +} + +/* + * Decrease INVITE session reference, destroy it when the reference count + * reaches zero. + */ +PJ_DEF(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv ) +{ + pj_atomic_value_t ref_cnt; + + PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL); + + ref_cnt = pj_atomic_dec_and_get(inv->ref_cnt); + pj_assert( ref_cnt >= 0); + if (ref_cnt == 0) { + inv_session_destroy(inv); + return PJ_EGONE; + } + return PJ_SUCCESS; +} + /* * Set session state. */ @@ -261,27 +320,7 @@ static void inv_set_state(pjsip_inv_session *inv, pjsip_inv_state state, if (inv->state == PJSIP_INV_STATE_DISCONNECTED && prev_state != PJSIP_INV_STATE_DISCONNECTED) { - if (inv->last_ack) { - pjsip_tx_data_dec_ref(inv->last_ack); - inv->last_ack = NULL; - } - if (inv->invite_req) { - pjsip_tx_data_dec_ref(inv->invite_req); - inv->invite_req = NULL; - } - if (inv->pending_bye) { - pjsip_tx_data_dec_ref(inv->pending_bye); - inv->pending_bye = NULL; - } - pjsip_100rel_end_session(inv); - pjsip_timer_end_session(inv); - pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod); - - /* Release the flip-flop pools */ - pj_pool_release(inv->pool_prov); - inv->pool_prov = NULL; - pj_pool_release(inv->pool_active); - inv->pool_active = NULL; + pjsip_inv_dec_ref(inv); } } @@ -838,6 +877,12 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uac( pjsip_dialog *dlg, inv = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_inv_session); pj_assert(inv != NULL); + status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt); + if (status != PJ_SUCCESS) { + pjsip_dlg_dec_lock(dlg); + return status; + } + inv->pool = dlg->pool; inv->role = PJSIP_ROLE_UAC; inv->state = PJSIP_INV_STATE_NULL; @@ -881,6 +926,7 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uac( pjsip_dialog *dlg, pjsip_100rel_attach(inv); /* Done */ + pjsip_inv_add_ref(inv); *p_inv = inv; pjsip_dlg_dec_lock(dlg); @@ -1471,6 +1517,12 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uas( pjsip_dialog *dlg, inv = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_inv_session); pj_assert(inv != NULL); + status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt); + if (status != PJ_SUCCESS) { + pjsip_dlg_dec_lock(dlg); + return status; + } + inv->pool = dlg->pool; inv->role = PJSIP_ROLE_UAS; inv->state = PJSIP_INV_STATE_NULL; @@ -1540,6 +1592,7 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uas( pjsip_dialog *dlg, } /* Done */ + pjsip_inv_add_ref(inv); pjsip_dlg_dec_lock(dlg); *p_inv = inv; -- cgit v1.2.3