Ignore:
Timestamp:
Feb 21, 2013 11:26:35 AM (11 years ago)
Author:
bennylp
Message:

Fixed #1617: major synchronization fixes in PJNATH with incorporation of group lock to avoid deadlock and crashes due to race conditions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/src/pjnath/turn_sock.c

    r4343 r4360  
    4747    void                *user_data; 
    4848 
    49     pj_lock_t           *lock; 
     49    pj_bool_t            is_destroying; 
     50    pj_grp_lock_t       *grp_lock; 
    5051 
    5152    pj_turn_alloc_param  alloc_param; 
     
    5354    pj_turn_sock_cfg     setting; 
    5455 
    55     pj_bool_t            destroy_request; 
    5656    pj_timer_entry       timer; 
    5757 
     
    9494 
    9595 
     96static void turn_sock_on_destroy(void *comp); 
    9697static void destroy(pj_turn_sock *turn_sock); 
    9798static void timer_cb(pj_timer_heap_t *th, pj_timer_entry *e); 
     
    169170    } 
    170171 
    171     /* Create lock */ 
    172     status = pj_lock_create_recursive_mutex(pool, turn_sock->obj_name,  
    173                                             &turn_sock->lock); 
    174     if (status != PJ_SUCCESS) { 
    175         destroy(turn_sock); 
    176         return status; 
    177     } 
     172    /* Session lock */ 
     173    if (setting && setting->grp_lock) { 
     174        turn_sock->grp_lock = setting->grp_lock; 
     175    } else { 
     176        status = pj_grp_lock_create(pool, NULL, &turn_sock->grp_lock); 
     177        if (status != PJ_SUCCESS) { 
     178            pj_pool_release(pool); 
     179            return status; 
     180        } 
     181    } 
     182 
     183    pj_grp_lock_add_ref(turn_sock->grp_lock); 
     184    pj_grp_lock_add_handler(turn_sock->grp_lock, pool, turn_sock, 
     185                            &turn_sock_on_destroy); 
    178186 
    179187    /* Init timer */ 
     
    187195    sess_cb.on_state = &turn_on_state; 
    188196    status = pj_turn_session_create(cfg, pool->obj_name, af, conn_type, 
    189                                     &sess_cb, 0, turn_sock, &turn_sock->sess); 
     197                                    turn_sock->grp_lock, &sess_cb, 0, 
     198                                    turn_sock, &turn_sock->sess); 
    190199    if (status != PJ_SUCCESS) { 
    191200        destroy(turn_sock); 
     
    204213 * Destroy. 
    205214 */ 
    206 static void destroy(pj_turn_sock *turn_sock) 
    207 { 
    208     if (turn_sock->lock) { 
    209         pj_lock_acquire(turn_sock->lock); 
    210     } 
    211  
    212     if (turn_sock->sess) { 
    213         pj_turn_session_set_user_data(turn_sock->sess, NULL); 
    214         pj_turn_session_shutdown(turn_sock->sess); 
    215         turn_sock->sess = NULL; 
    216     } 
    217  
    218     if (turn_sock->active_sock) { 
    219         pj_activesock_set_user_data(turn_sock->active_sock, NULL); 
    220         pj_activesock_close(turn_sock->active_sock); 
    221         turn_sock->active_sock = NULL; 
    222     } 
    223  
    224     if (turn_sock->lock) { 
    225         pj_lock_release(turn_sock->lock); 
    226         pj_lock_destroy(turn_sock->lock); 
    227         turn_sock->lock = NULL; 
    228     } 
     215static void turn_sock_on_destroy(void *comp) 
     216{ 
     217    pj_turn_sock *turn_sock = (pj_turn_sock*) comp; 
    229218 
    230219    if (turn_sock->pool) { 
    231220        pj_pool_t *pool = turn_sock->pool; 
     221        PJ_LOG(4,(turn_sock->obj_name, "TURN socket destroyed")); 
    232222        turn_sock->pool = NULL; 
    233223        pj_pool_release(pool); 
     
    235225} 
    236226 
     227static void destroy(pj_turn_sock *turn_sock) 
     228{ 
     229    PJ_LOG(4,(turn_sock->obj_name, "TURN socket destroy request, ref_cnt=%d", 
     230              pj_grp_lock_get_ref(turn_sock->grp_lock))); 
     231 
     232    pj_grp_lock_acquire(turn_sock->grp_lock); 
     233    if (turn_sock->is_destroying) { 
     234        pj_grp_lock_release(turn_sock->grp_lock); 
     235        return; 
     236    } 
     237 
     238    turn_sock->is_destroying = PJ_TRUE; 
     239    if (turn_sock->sess) 
     240        pj_turn_session_shutdown(turn_sock->sess); 
     241    if (turn_sock->active_sock) 
     242        pj_activesock_close(turn_sock->active_sock); 
     243    pj_grp_lock_dec_ref(turn_sock->grp_lock); 
     244    pj_grp_lock_release(turn_sock->grp_lock); 
     245} 
    237246 
    238247PJ_DEF(void) pj_turn_sock_destroy(pj_turn_sock *turn_sock) 
    239248{ 
    240     pj_lock_acquire(turn_sock->lock); 
    241     turn_sock->destroy_request = PJ_TRUE; 
     249    pj_grp_lock_acquire(turn_sock->grp_lock); 
     250    if (turn_sock->is_destroying) { 
     251        pj_grp_lock_release(turn_sock->grp_lock); 
     252        return; 
     253    } 
    242254 
    243255    if (turn_sock->sess) { 
     
    247259         * destroy ourselves. 
    248260         */ 
    249         pj_lock_release(turn_sock->lock); 
    250261    } else { 
    251         pj_lock_release(turn_sock->lock); 
    252262        destroy(turn_sock); 
    253263    } 
    254264 
     265    pj_grp_lock_release(turn_sock->grp_lock); 
    255266} 
    256267 
     
    268279    switch (eid) { 
    269280    case TIMER_DESTROY: 
    270         PJ_LOG(5,(turn_sock->obj_name, "Destroying TURN")); 
    271281        destroy(turn_sock); 
    272282        break; 
     
    338348PJ_DEF(pj_status_t) pj_turn_sock_lock(pj_turn_sock *turn_sock) 
    339349{ 
    340     return pj_lock_acquire(turn_sock->lock); 
     350    return pj_grp_lock_acquire(turn_sock->grp_lock); 
    341351} 
    342352 
     
    346356PJ_DEF(pj_status_t) pj_turn_sock_unlock(pj_turn_sock *turn_sock) 
    347357{ 
    348     return pj_lock_release(turn_sock->lock); 
     358    return pj_grp_lock_release(turn_sock->grp_lock); 
    349359} 
    350360 
     
    381391    PJ_ASSERT_RETURN(turn_sock && domain, PJ_EINVAL); 
    382392    PJ_ASSERT_RETURN(turn_sock->sess, PJ_EINVALIDOP); 
     393 
     394    pj_grp_lock_acquire(turn_sock->grp_lock); 
    383395 
    384396    /* Copy alloc param. We will call session_alloc() only after the  
     
    396408        if (status != PJ_SUCCESS) { 
    397409            sess_fail(turn_sock, "Error setting credential", status); 
     410            pj_grp_lock_release(turn_sock->grp_lock); 
    398411            return status; 
    399412        } 
     
    405418    if (status != PJ_SUCCESS) { 
    406419        sess_fail(turn_sock, "Error setting TURN server", status); 
     420        pj_grp_lock_release(turn_sock->grp_lock); 
    407421        return status; 
    408422    } 
     
    411425     * to RESOLVED state. 
    412426     */ 
    413  
     427    pj_grp_lock_release(turn_sock->grp_lock); 
    414428    return PJ_SUCCESS; 
    415429} 
     
    473487        return PJ_FALSE; 
    474488 
     489    pj_grp_lock_acquire(turn_sock->grp_lock); 
     490 
    475491    /* TURN session may have already been destroyed here. 
    476492     * See ticket #1557 (http://trac.pjsip.org/repos/ticket/1557). 
     
    478494    if (!turn_sock->sess) { 
    479495        sess_fail(turn_sock, "TURN session already destroyed", status); 
     496        pj_grp_lock_release(turn_sock->grp_lock); 
    480497        return PJ_FALSE; 
    481498    } 
     
    483500    if (status != PJ_SUCCESS) { 
    484501        sess_fail(turn_sock, "TCP connect() error", status); 
     502        pj_grp_lock_release(turn_sock->grp_lock); 
    485503        return PJ_FALSE; 
    486504    } 
     
    501519    if (status != PJ_SUCCESS) { 
    502520        sess_fail(turn_sock, "Error sending ALLOCATE", status); 
     521        pj_grp_lock_release(turn_sock->grp_lock); 
    503522        return PJ_FALSE; 
    504523    } 
    505524 
     525    pj_grp_lock_release(turn_sock->grp_lock); 
    506526    return PJ_TRUE; 
    507527} 
     
    563583 
    564584    turn_sock = (pj_turn_sock*) pj_activesock_get_user_data(asock); 
    565     pj_lock_acquire(turn_sock->lock); 
    566  
    567     if (status == PJ_SUCCESS && turn_sock->sess) { 
     585    pj_grp_lock_acquire(turn_sock->grp_lock); 
     586 
     587    if (status == PJ_SUCCESS && turn_sock->sess && !turn_sock->is_destroying) { 
    568588        /* Report incoming packet to TURN session, repeat while we have 
    569589         * "packet" in the buffer (required for stream-oriented transports) 
     
    615635 
    616636on_return: 
    617     pj_lock_release(turn_sock->lock); 
     637    pj_grp_lock_release(turn_sock->grp_lock); 
    618638 
    619639    return ret; 
     
    635655    pj_status_t status; 
    636656 
    637     if (turn_sock == NULL) { 
     657    if (turn_sock == NULL || turn_sock->is_destroying) { 
    638658        /* We've been destroyed */ 
    639659        // https://trac.pjsip.org/repos/ticket/1316 
     
    681701    pj_turn_sock *turn_sock = (pj_turn_sock*)  
    682702                           pj_turn_session_get_user_data(sess); 
    683     if (turn_sock == NULL) { 
     703    if (turn_sock == NULL || turn_sock->is_destroying) { 
    684704        /* We've been destroyed */ 
    685705        return; 
     
    730750        int sock_type; 
    731751        pj_sock_t sock; 
     752        pj_activesock_cfg asock_cfg; 
    732753        pj_activesock_cb asock_cb; 
    733754        pj_sockaddr bound_addr, *cfg_bind_addr; 
     
    791812 
    792813        /* Create active socket */ 
     814        pj_activesock_cfg_default(&asock_cfg); 
     815        asock_cfg.grp_lock = turn_sock->grp_lock; 
     816 
    793817        pj_bzero(&asock_cb, sizeof(asock_cb)); 
    794818        asock_cb.on_data_read = &on_data_read; 
    795819        asock_cb.on_connect_complete = &on_connect_complete; 
    796820        status = pj_activesock_create(turn_sock->pool, sock, 
    797                                       sock_type, NULL, 
     821                                      sock_type, &asock_cfg, 
    798822                                      turn_sock->cfg.ioqueue, &asock_cb,  
    799823                                      turn_sock, 
     
    836860        pj_turn_session_set_user_data(sess, NULL); 
    837861 
    838         if (turn_sock->timer.id) { 
    839             pj_timer_heap_cancel(turn_sock->cfg.timer_heap, &turn_sock->timer); 
    840             turn_sock->timer.id = 0; 
    841         } 
    842  
    843         turn_sock->timer.id = TIMER_DESTROY; 
    844         pj_timer_heap_schedule(turn_sock->cfg.timer_heap, &turn_sock->timer,  
    845                                &delay); 
    846     } 
    847 } 
    848  
    849  
     862        pj_timer_heap_cancel_if_active(turn_sock->cfg.timer_heap, 
     863                                       &turn_sock->timer, 0); 
     864        pj_timer_heap_schedule_w_grp_lock(turn_sock->cfg.timer_heap, 
     865                                          &turn_sock->timer, 
     866                                          &delay, TIMER_DESTROY, 
     867                                          turn_sock->grp_lock); 
     868    } 
     869} 
     870 
     871 
Note: See TracChangeset for help on using the changeset viewer.