Changeset 5435 for pjproject/trunk


Ignore:
Timestamp:
Aug 30, 2016 8:40:18 AM (8 years ago)
Author:
riza
Message:

Re #1959: Add reference counter to pjsip_inv_session to avoid race condition.

Location:
pjproject/trunk/pjsip
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h

    r5109 r5435  
    384384 * that the flip-flop pool's lifetimes are synchronized to the 
    385385 * SDP offer-answer negotiation. 
     386 * 
     387 * The lifetime of this session is controlled by the reference counter in this 
     388 * structure, which is manipulated by calling #pjsip_inv_add_ref and 
     389 * #pjsip_inv_dec_ref. When the reference counter has reached zero, then 
     390 * this session will be destroyed. 
    386391 */ 
    387392struct pjsip_inv_session 
     
    413418    pj_bool_t            following_fork;            /**< Internal, following 
    414419                                                         forked media?      */ 
     420    pj_atomic_t         *ref_cnt;                   /**< Reference counter. */ 
    415421}; 
    416422 
     
    629635                                          unsigned options, 
    630636                                          pjsip_inv_session **p_inv); 
     637 
     638 
     639/** 
     640 * Add reference counter to the INVITE session. The reference counter controls 
     641 * the life time of the session, ie. when the counter reaches zero, then it  
     642 * will be destroyed. 
     643 * 
     644 * @param inv       The INVITE session. 
     645 * @return          PJ_SUCCESS if the INVITE session reference counter 
     646 *                  was increased. 
     647 */ 
     648PJ_DECL(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv ); 
     649 
     650/** 
     651 * Decrement reference counter of the INVITE session. 
     652 * When the session is no longer used, it will be destroyed and 
     653 * caller is informed with PJ_EGONE return status. 
     654 * 
     655 * @param inv       The INVITE session. 
     656 * @return          PJ_SUCCESS if the INVITE session reference counter 
     657 *                  was decreased. A status PJ_EGONE will be returned to  
     658 *                  inform that session is destroyed. 
     659 */ 
     660PJ_DECL(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv ); 
    631661 
    632662 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r5398 r5435  
    196196 
    197197/* 
     198 * Add reference to INVITE session. 
     199 */ 
     200PJ_DEF(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv ) 
     201{ 
     202    PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL); 
     203 
     204    pj_atomic_inc(inv->ref_cnt); 
     205 
     206    return PJ_SUCCESS; 
     207} 
     208 
     209static void inv_session_destroy(pjsip_inv_session *inv) 
     210{ 
     211    if (inv->last_ack) { 
     212        pjsip_tx_data_dec_ref(inv->last_ack); 
     213        inv->last_ack = NULL; 
     214    } 
     215    if (inv->invite_req) { 
     216        pjsip_tx_data_dec_ref(inv->invite_req); 
     217        inv->invite_req = NULL; 
     218    } 
     219    if (inv->pending_bye) { 
     220        pjsip_tx_data_dec_ref(inv->pending_bye); 
     221        inv->pending_bye = NULL; 
     222    } 
     223    pjsip_100rel_end_session(inv); 
     224    pjsip_timer_end_session(inv); 
     225    pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod); 
     226 
     227    /* Release the flip-flop pools */ 
     228    pj_pool_release(inv->pool_prov); 
     229    inv->pool_prov = NULL; 
     230    pj_pool_release(inv->pool_active); 
     231    inv->pool_active = NULL; 
     232 
     233    pj_atomic_destroy(inv->ref_cnt); 
     234    inv->ref_cnt = NULL; 
     235} 
     236 
     237/* 
     238 * Decrease INVITE session reference, destroy it when the reference count 
     239 * reaches zero. 
     240 */ 
     241PJ_DEF(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv ) 
     242{ 
     243    pj_atomic_value_t ref_cnt; 
     244 
     245    PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL); 
     246 
     247    ref_cnt = pj_atomic_dec_and_get(inv->ref_cnt); 
     248    pj_assert( ref_cnt >= 0); 
     249    if (ref_cnt == 0) { 
     250        inv_session_destroy(inv); 
     251        return PJ_EGONE; 
     252    }  
     253    return PJ_SUCCESS;     
     254} 
     255 
     256/* 
    198257 * Set session state. 
    199258 */ 
     
    262321        prev_state != PJSIP_INV_STATE_DISCONNECTED)  
    263322    { 
    264         if (inv->last_ack) { 
    265             pjsip_tx_data_dec_ref(inv->last_ack); 
    266             inv->last_ack = NULL; 
    267         } 
    268         if (inv->invite_req) { 
    269             pjsip_tx_data_dec_ref(inv->invite_req); 
    270             inv->invite_req = NULL; 
    271         } 
    272         if (inv->pending_bye) { 
    273             pjsip_tx_data_dec_ref(inv->pending_bye); 
    274             inv->pending_bye = NULL; 
    275         } 
    276         pjsip_100rel_end_session(inv); 
    277         pjsip_timer_end_session(inv); 
    278         pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod); 
    279  
    280         /* Release the flip-flop pools */ 
    281         pj_pool_release(inv->pool_prov); 
    282         inv->pool_prov = NULL; 
    283         pj_pool_release(inv->pool_active); 
    284         inv->pool_active = NULL; 
     323        pjsip_inv_dec_ref(inv); 
    285324    } 
    286325} 
     
    839878    pj_assert(inv != NULL); 
    840879 
     880    status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt); 
     881    if (status != PJ_SUCCESS) { 
     882        pjsip_dlg_dec_lock(dlg); 
     883        return status; 
     884    } 
     885 
    841886    inv->pool = dlg->pool; 
    842887    inv->role = PJSIP_ROLE_UAC; 
     
    882927 
    883928    /* Done */ 
     929    pjsip_inv_add_ref(inv); 
    884930    *p_inv = inv; 
    885931 
     
    14721518    pj_assert(inv != NULL); 
    14731519 
     1520    status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt); 
     1521    if (status != PJ_SUCCESS) { 
     1522        pjsip_dlg_dec_lock(dlg); 
     1523        return status; 
     1524    } 
     1525 
    14741526    inv->pool = dlg->pool; 
    14751527    inv->role = PJSIP_ROLE_UAS; 
     
    15411593 
    15421594    /* Done */ 
     1595    pjsip_inv_add_ref(inv); 
    15431596    pjsip_dlg_dec_lock(dlg); 
    15441597    *p_inv = inv; 
Note: See TracChangeset for help on using the changeset viewer.