Ignore:
Timestamp:
Sep 9, 2015 9:24:06 AM (4 years ago)
Author:
nanang
Message:

Fix #1883: Check transport validity after getting transport manager lock in pjsip_transport_add/dec_ref() as transport may already be destroyed by other thread.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip/sip_transport.c

    r5097 r5173  
    953953} 
    954954 
     955 
     956static pj_bool_t is_transport_valid(pjsip_transport *tp, pjsip_tpmgr *tpmgr, 
     957                                    const pjsip_transport_key *key, 
     958                                    int key_len) 
     959{ 
     960    return (pj_hash_get(tpmgr->table, key, key_len, NULL) == (void*)tp); 
     961} 
     962 
    955963/* 
    956964 * Add ref. 
     
    958966PJ_DEF(pj_status_t) pjsip_transport_add_ref( pjsip_transport *tp ) 
    959967{ 
     968    pjsip_tpmgr *tpmgr; 
     969    pjsip_transport_key key; 
     970    int key_len; 
     971 
    960972    PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL); 
    961973 
     974    /* Cache some vars for checking transport validity later */ 
     975    tpmgr = tp->tpmgr; 
     976    key_len = sizeof(tp->key.type) + tp->addr_len; 
     977    pj_memcpy(&key, &tp->key, key_len); 
     978 
    962979    if (pj_atomic_inc_and_get(tp->ref_cnt) == 1) { 
    963         pj_lock_acquire(tp->tpmgr->lock); 
    964         /* Verify again. */ 
    965         if (pj_atomic_get(tp->ref_cnt) == 1) { 
     980        pj_lock_acquire(tpmgr->lock); 
     981        /* Verify again. But first, make sure transport is still valid 
     982         * (see #1883). 
     983         */ 
     984        if (is_transport_valid(tp, tpmgr, &key, key_len) && 
     985            pj_atomic_get(tp->ref_cnt) == 1) 
     986        { 
    966987            if (tp->idle_timer.id != PJ_FALSE) { 
    967988                pjsip_endpt_cancel_timer(tp->tpmgr->endpt, &tp->idle_timer); 
     
    969990            } 
    970991        } 
    971         pj_lock_release(tp->tpmgr->lock); 
     992        pj_lock_release(tpmgr->lock); 
    972993    } 
    973994 
     
    9801001PJ_DEF(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp ) 
    9811002{ 
     1003    pjsip_tpmgr *tpmgr; 
     1004    pjsip_transport_key key; 
     1005    int key_len; 
     1006 
    9821007    PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL); 
    983  
    9841008    pj_assert(pj_atomic_get(tp->ref_cnt) > 0); 
    9851009 
     1010    /* Cache some vars for checking transport validity later */ 
     1011    tpmgr = tp->tpmgr; 
     1012    key_len = sizeof(tp->key.type) + tp->addr_len; 
     1013    pj_memcpy(&key, &tp->key, key_len); 
     1014 
    9861015    if (pj_atomic_dec_and_get(tp->ref_cnt) == 0) { 
    987         pj_lock_acquire(tp->tpmgr->lock); 
     1016        pj_lock_acquire(tpmgr->lock); 
    9881017        /* Verify again. Do not register timer if the transport is 
    989          * being destroyed. 
     1018         * being destroyed. But first, make sure transport is still valid 
     1019         * (see #1883). 
    9901020         */ 
    991         if (pj_atomic_get(tp->ref_cnt) == 0 && !tp->is_destroying) { 
     1021        if (is_transport_valid(tp, tpmgr, &key, key_len) && 
     1022            !tp->is_destroying && pj_atomic_get(tp->ref_cnt) == 0) 
     1023        { 
    9921024            pj_time_val delay; 
    9931025             
     
    10101042                                       &delay); 
    10111043        } 
    1012         pj_lock_release(tp->tpmgr->lock); 
     1044        pj_lock_release(tpmgr->lock); 
    10131045    } 
    10141046 
     
    10781110    void *entry; 
    10791111 
     1112    tp->is_destroying = PJ_TRUE; 
     1113 
    10801114    TRACE_((THIS_FILE, "Transport %s is being destroyed", tp->obj_name)); 
    10811115 
    10821116    pj_lock_acquire(tp->lock); 
    10831117    pj_lock_acquire(mgr->lock); 
    1084  
    1085     tp->is_destroying = PJ_TRUE; 
    10861118 
    10871119    /* 
Note: See TracChangeset for help on using the changeset viewer.