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/ice_session.c

    r4357 r4360  
    9898}; 
    9999 
     100#define THIS_FILE               "ice_session.c" 
    100101#define CHECK_NAME_LEN          128 
    101102#define LOG4(expr)              PJ_LOG(4,expr) 
     
    135136static void on_ice_complete(pj_ice_sess *ice, pj_status_t status); 
    136137static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now); 
     138static void ice_on_destroy(void *obj); 
    137139static void destroy_ice(pj_ice_sess *ice, 
    138140                        pj_status_t reason); 
     
    289291    status = pj_stun_session_create(&ice->stun_cfg, NULL,  
    290292                                    &sess_cb, PJ_TRUE, 
     293                                    ice->grp_lock, 
    291294                                    &comp->stun_sess); 
    292295    if (status != PJ_SUCCESS) 
     
    333336                                       const pj_str_t *local_ufrag, 
    334337                                       const pj_str_t *local_passwd, 
     338                                       pj_grp_lock_t *grp_lock, 
    335339                                       pj_ice_sess **p_ice) 
    336340{ 
     
    360364                     name, ice); 
    361365 
    362     status = pj_mutex_create_recursive(pool, ice->obj_name,  
    363                                        &ice->mutex); 
    364     if (status != PJ_SUCCESS) { 
    365         destroy_ice(ice, status); 
    366         return status; 
    367     } 
     366    if (grp_lock) { 
     367        ice->grp_lock = grp_lock; 
     368    } else { 
     369        status = pj_grp_lock_create(pool, NULL, &ice->grp_lock); 
     370        if (status != PJ_SUCCESS) { 
     371            pj_pool_release(pool); 
     372            return status; 
     373        } 
     374    } 
     375 
     376    pj_grp_lock_add_ref(ice->grp_lock); 
     377    pj_grp_lock_add_handler(ice->grp_lock, pool, ice, 
     378                            &ice_on_destroy); 
    368379 
    369380    pj_memcpy(&ice->cb, cb, sizeof(*cb)); 
     
    445456 
    446457/* 
     458 * Callback to really destroy the session 
     459 */ 
     460static void ice_on_destroy(void *obj) 
     461{ 
     462    pj_ice_sess *ice = (pj_ice_sess*) obj; 
     463 
     464    if (ice->pool) { 
     465        pj_pool_t *pool = ice->pool; 
     466        ice->pool = NULL; 
     467        pj_pool_release(pool); 
     468    } 
     469    LOG4((THIS_FILE, "ICE session %p destroyed", ice)); 
     470} 
     471 
     472/* 
    447473 * Destroy 
    448474 */ 
     
    453479 
    454480    if (reason == PJ_SUCCESS) { 
    455         LOG4((ice->obj_name, "Destroying ICE session")); 
     481        LOG4((ice->obj_name, "Destroying ICE session %p", ice)); 
     482    } 
     483 
     484    pj_grp_lock_acquire(ice->grp_lock); 
     485 
     486    if (ice->is_destroying) { 
     487        pj_grp_lock_release(ice->grp_lock); 
     488        return; 
    456489    } 
    457490 
    458491    ice->is_destroying = PJ_TRUE; 
    459492 
    460     /* Let other callbacks finish */ 
    461     if (ice->mutex) { 
    462         pj_mutex_lock(ice->mutex); 
    463         pj_mutex_unlock(ice->mutex); 
    464     } 
    465  
    466     if (ice->timer.id) { 
    467         pj_timer_heap_cancel(ice->stun_cfg.timer_heap,  
    468                              &ice->timer); 
    469         ice->timer.id = PJ_FALSE; 
    470     } 
     493    pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, 
     494                                   &ice->timer, PJ_FALSE); 
    471495 
    472496    for (i=0; i<ice->comp_cnt; ++i) { 
     
    477501    } 
    478502 
    479     if (ice->clist.timer.id) { 
    480         pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->clist.timer); 
    481         ice->clist.timer.id = PJ_FALSE; 
    482     } 
    483  
    484     if (ice->mutex) { 
    485         pj_mutex_destroy(ice->mutex); 
    486         ice->mutex = NULL; 
    487     } 
    488  
    489     if (ice->pool) { 
    490         pj_pool_t *pool = ice->pool; 
    491         ice->pool = NULL; 
    492         pj_pool_release(pool); 
    493     } 
     503    pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, 
     504                                   &ice->clist.timer, 
     505                                   PJ_FALSE); 
     506 
     507    pj_grp_lock_dec_ref(ice->grp_lock); 
     508    pj_grp_lock_release(ice->grp_lock); 
    494509} 
    495510 
     
    710725    PJ_ASSERT_RETURN(comp_id <= ice->comp_cnt, PJ_EINVAL); 
    711726 
    712     pj_mutex_lock(ice->mutex); 
     727    pj_grp_lock_acquire(ice->grp_lock); 
    713728 
    714729    if (ice->lcand_cnt >= PJ_ARRAY_SIZE(ice->lcand)) { 
     
    750765 
    751766on_error: 
    752     pj_mutex_unlock(ice->mutex); 
     767    pj_grp_lock_release(ice->grp_lock); 
    753768    return status; 
    754769} 
     
    767782    *cand_id = -1; 
    768783 
    769     pj_mutex_lock(ice->mutex); 
     784    pj_grp_lock_acquire(ice->grp_lock); 
    770785 
    771786    /* First find in valid list if we have nominated pair */ 
     
    775790        if (check->lcand->comp_id == comp_id) { 
    776791            *cand_id = GET_LCAND_ID(check->lcand); 
    777             pj_mutex_unlock(ice->mutex); 
     792            pj_grp_lock_release(ice->grp_lock); 
    778793            return PJ_SUCCESS; 
    779794        } 
     
    787802        { 
    788803            *cand_id = GET_LCAND_ID(lcand); 
    789             pj_mutex_unlock(ice->mutex); 
     804            pj_grp_lock_release(ice->grp_lock); 
    790805            return PJ_SUCCESS; 
    791806        } 
     
    800815        { 
    801816            *cand_id = GET_LCAND_ID(lcand); 
    802             pj_mutex_unlock(ice->mutex); 
     817            pj_grp_lock_release(ice->grp_lock); 
    803818            return PJ_SUCCESS; 
    804819        } 
     
    812827        { 
    813828            *cand_id = GET_LCAND_ID(lcand); 
    814             pj_mutex_unlock(ice->mutex); 
     829            pj_grp_lock_release(ice->grp_lock); 
    815830            return PJ_SUCCESS; 
    816831        } 
     
    818833 
    819834    /* Still no candidate is found! :( */ 
    820     pj_mutex_unlock(ice->mutex); 
     835    pj_grp_lock_release(ice->grp_lock); 
    821836 
    822837    pj_assert(!"Should have a candidate by now"); 
     
    11281143    pj_ice_sess *ice = (pj_ice_sess*) te->user_data; 
    11291144    enum timer_type type = (enum timer_type)te->id; 
    1130     pj_bool_t has_mutex = PJ_TRUE; 
    11311145 
    11321146    PJ_UNUSED_ARG(th); 
    11331147 
    1134     pj_mutex_lock(ice->mutex); 
     1148    pj_grp_lock_acquire(ice->grp_lock); 
    11351149 
    11361150    te->id = TIMER_NONE; 
     1151 
     1152    if (ice->is_destroying) { 
     1153        /* Stray timer, could happen when destroy is invoked while callback 
     1154         * is pending. */ 
     1155        pj_grp_lock_release(ice->grp_lock); 
     1156        return; 
     1157    } 
    11371158 
    11381159    switch (type) { 
     
    11581179            ice_status = ice->ice_status; 
    11591180            on_ice_complete = ice->cb.on_ice_complete; 
    1160             has_mutex = PJ_FALSE; 
    1161             pj_mutex_unlock(ice->mutex); 
    11621181 
    11631182            /* Notify app about ICE completion*/ 
     
    11771196    } 
    11781197 
    1179     if (has_mutex) 
    1180         pj_mutex_unlock(ice->mutex); 
     1198    pj_grp_lock_release(ice->grp_lock); 
    11811199} 
    11821200 
     
    12361254        pj_time_val_normalize(&delay); 
    12371255 
    1238         ice->timer.id = TIMER_KEEP_ALIVE; 
    1239         pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay); 
     1256        pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, 
     1257                                          &ice->timer, &delay, 
     1258                                          TIMER_KEEP_ALIVE, 
     1259                                          ice->grp_lock); 
    12401260 
    12411261    } else { 
     
    12511271        ice->ice_status = status; 
    12521272     
    1253         if (ice->timer.id != TIMER_NONE) { 
    1254             pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 
    1255             ice->timer.id = TIMER_NONE; 
    1256         } 
     1273        pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, &ice->timer, 
     1274                                       TIMER_NONE); 
    12571275 
    12581276        /* Log message */ 
     
    12671285            pj_time_val delay = {0, 0}; 
    12681286 
    1269             ice->timer.id = TIMER_COMPLETION_CALLBACK; 
    1270             pj_timer_heap_schedule(ice->stun_cfg.timer_heap,  
    1271                                    &ice->timer, &delay); 
     1287            pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, 
     1288                                              &ice->timer, &delay, 
     1289                                              TIMER_COMPLETION_CALLBACK, 
     1290                                              ice->grp_lock); 
    12721291        } 
    12731292    } 
     
    14971516                    pj_time_val_normalize(&delay); 
    14981517 
    1499                     ice->timer.id = TIMER_CONTROLLED_WAIT_NOM; 
    1500                     pj_timer_heap_schedule(ice->stun_cfg.timer_heap,  
    1501                                            &ice->timer, 
    1502                                            &delay); 
     1518                    pj_timer_heap_schedule_w_grp_lock( 
     1519                                        ice->stun_cfg.timer_heap, 
     1520                                        &ice->timer, &delay, 
     1521                                        TIMER_CONTROLLED_WAIT_NOM, 
     1522                                        ice->grp_lock); 
    15031523 
    15041524                    LOG5((ice->obj_name,  
     
    15761596              ice->opt.nominated_check_delay)); 
    15771597 
    1578         if (ice->timer.id != TIMER_NONE) { 
    1579             pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 
    1580             ice->timer.id = TIMER_NONE; 
    1581         } 
     1598        pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, &ice->timer, 
     1599                                       TIMER_NONE); 
    15821600 
    15831601        /* All components have valid pair. Let connectivity checks run for 
     
    15881606        pj_time_val_normalize(&delay); 
    15891607 
    1590         ice->timer.id = TIMER_START_NOMINATED_CHECK; 
    1591         pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay); 
     1608        pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, 
     1609                                          &ice->timer, &delay, 
     1610                                          TIMER_START_NOMINATED_CHECK, 
     1611                                          ice->grp_lock); 
    15921612        return PJ_FALSE; 
    15931613    } 
     
    16191639                     PJ_ETOOMANY); 
    16201640 
    1621     pj_mutex_lock(ice->mutex); 
     1641    pj_grp_lock_acquire(ice->grp_lock); 
    16221642 
    16231643    /* Save credentials */ 
     
    16671687 
    16681688            if (clist->count >= PJ_ICE_MAX_CHECKS) { 
    1669                 pj_mutex_unlock(ice->mutex); 
     1689                pj_grp_lock_release(ice->grp_lock); 
    16701690                return PJ_ETOOMANY; 
    16711691            }  
     
    16951715    if (clist->count == 0) { 
    16961716        LOG4((ice->obj_name,  "Error: no checklist can be created")); 
    1697         pj_mutex_unlock(ice->mutex); 
     1717        pj_grp_lock_release(ice->grp_lock); 
    16981718        return PJ_ENOTFOUND; 
    16991719    } 
     
    17051725    status = prune_checklist(ice, clist); 
    17061726    if (status != PJ_SUCCESS) { 
    1707         pj_mutex_unlock(ice->mutex); 
     1727        pj_grp_lock_release(ice->grp_lock); 
    17081728        return status; 
    17091729    } 
     
    17321752    dump_checklist("Checklist created:", ice, clist); 
    17331753 
    1734     pj_mutex_unlock(ice->mutex); 
     1754    pj_grp_lock_release(ice->grp_lock); 
    17351755 
    17361756    return PJ_SUCCESS; 
     
    18511871    clist = td->clist; 
    18521872 
    1853     if (ice->is_destroying) 
    1854         return PJ_SUCCESS; 
    1855  
    1856     pj_mutex_lock(ice->mutex); 
     1873    pj_grp_lock_acquire(ice->grp_lock); 
    18571874 
    18581875    if (ice->is_destroying) { 
    1859         pj_mutex_unlock(ice->mutex); 
     1876        pj_grp_lock_release(ice->grp_lock); 
    18601877        return PJ_SUCCESS; 
    18611878    } 
     
    18791896            status = perform_check(ice, clist, i, ice->is_nominating); 
    18801897            if (status != PJ_SUCCESS) { 
    1881                 pj_mutex_unlock(ice->mutex); 
     1898                pj_grp_lock_release(ice->grp_lock); 
    18821899                pj_log_pop_indent(); 
    18831900                return status; 
     
    18991916                status = perform_check(ice, clist, i, ice->is_nominating); 
    19001917                if (status != PJ_SUCCESS) { 
    1901                     pj_mutex_unlock(ice->mutex); 
     1918                    pj_grp_lock_release(ice->grp_lock); 
    19021919                    pj_log_pop_indent(); 
    19031920                    return status; 
     
    19161933        pj_time_val timeout = {0, PJ_ICE_TA_VAL}; 
    19171934 
    1918         te->id = PJ_TRUE; 
    19191935        pj_time_val_normalize(&timeout); 
    1920         pj_timer_heap_schedule(th, te, &timeout); 
    1921     } 
    1922  
    1923     pj_mutex_unlock(ice->mutex); 
     1936        pj_timer_heap_schedule_w_grp_lock(th, te, &timeout, PJ_TRUE, 
     1937                                          ice->grp_lock); 
     1938    } 
     1939 
     1940    pj_grp_lock_release(ice->grp_lock); 
    19241941    pj_log_pop_indent(); 
    19251942    return PJ_SUCCESS; 
     
    19411958    /* Stop our timer if it's active */ 
    19421959    if (ice->timer.id == TIMER_START_NOMINATED_CHECK) { 
    1943         pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 
    1944         ice->timer.id = TIMER_NONE; 
     1960        pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, &ice->timer, 
     1961                                       TIMER_NONE); 
    19451962    } 
    19461963 
     
    19701987 
    19711988    /* And (re)start the periodic check */ 
    1972     if (ice->clist.timer.id) { 
    1973         pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->clist.timer); 
    1974         ice->clist.timer.id = PJ_FALSE; 
    1975     } 
    1976  
    1977     ice->clist.timer.id = PJ_TRUE; 
     1989    pj_timer_heap_cancel_if_active(ice->stun_cfg.timer_heap, 
     1990                                   &ice->clist.timer, PJ_FALSE); 
     1991 
    19781992    delay.sec = delay.msec = 0; 
    1979     status = pj_timer_heap_schedule(ice->stun_cfg.timer_heap,  
    1980                                     &ice->clist.timer, &delay); 
    1981     if (status != PJ_SUCCESS) { 
    1982         ice->clist.timer.id = PJ_FALSE; 
    1983     } else { 
     1993    status = pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, 
     1994                                               &ice->clist.timer, &delay, 
     1995                                               PJ_TRUE, 
     1996                                               ice->grp_lock); 
     1997    if (status == PJ_SUCCESS) { 
    19841998        LOG5((ice->obj_name, "Periodic timer rescheduled..")); 
    19851999    } 
     
    20312045 
    20322046    /* Lock session */ 
    2033     pj_mutex_lock(ice->mutex); 
     2047    pj_grp_lock_acquire(ice->grp_lock); 
    20342048 
    20352049    LOG4((ice->obj_name, "Starting ICE check..")); 
     
    20612075    if (i == clist->count) { 
    20622076        pj_assert(!"Unable to find checklist for component 1"); 
    2063         pj_mutex_unlock(ice->mutex); 
     2077        pj_grp_lock_release(ice->grp_lock); 
    20642078        pj_log_pop_indent(); 
    20652079        return PJNATH_EICEINCOMPID; 
     
    21152129     * return start_periodic_check(ice->stun_cfg.timer_heap, &clist->timer); 
    21162130     */ 
    2117     clist->timer.id = PJ_TRUE; 
    21182131    delay.sec = delay.msec = 0; 
    2119     status = pj_timer_heap_schedule(ice->stun_cfg.timer_heap,  
    2120                                     &clist->timer, &delay); 
     2132    status = pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap, 
     2133                                               &clist->timer, &delay, 
     2134                                               PJ_TRUE, ice->grp_lock); 
    21212135    if (status != PJ_SUCCESS) { 
    21222136        clist->timer.id = PJ_FALSE; 
    21232137    } 
    21242138 
    2125     pj_mutex_unlock(ice->mutex); 
     2139    pj_grp_lock_release(ice->grp_lock); 
    21262140    pj_log_pop_indent(); 
    21272141    return status; 
     
    21442158    pj_ice_sess *ice = sd->ice; 
    21452159    pj_ice_msg_data *msg_data = (pj_ice_msg_data*) token; 
     2160    pj_status_t status; 
    21462161     
    2147     return (*ice->cb.on_tx_pkt)(ice, sd->comp_id, msg_data->transport_id, 
    2148                                 pkt, pkt_size, dst_addr, addr_len); 
     2162    pj_grp_lock_acquire(ice->grp_lock); 
     2163 
     2164    if (ice->is_destroying) { 
     2165        /* Stray retransmit timer that could happen while 
     2166         * we're being destroyed */ 
     2167        pj_grp_lock_release(ice->grp_lock); 
     2168        return PJ_EINVALIDOP; 
     2169    } 
     2170 
     2171    status = (*ice->cb.on_tx_pkt)(ice, sd->comp_id, msg_data->transport_id, 
     2172                                  pkt, pkt_size, dst_addr, addr_len); 
     2173 
     2174    pj_grp_lock_release(ice->grp_lock); 
     2175    return status; 
    21492176} 
    21502177 
     
    21812208    check->tdata = NULL; 
    21822209 
    2183     pj_mutex_lock(ice->mutex); 
     2210    pj_grp_lock_acquire(ice->grp_lock); 
     2211 
     2212    if (ice->is_destroying) { 
     2213        /* Not sure if this is possible but just in case */ 
     2214        pj_grp_lock_release(ice->grp_lock); 
     2215        return; 
     2216    } 
    21842217 
    21852218    /* Init lcand to NULL. lcand will be found from the mapped address 
     
    22322265                          check->nominated || ice->is_nominating); 
    22332266            pj_log_pop_indent(); 
    2234             pj_mutex_unlock(ice->mutex); 
     2267            pj_grp_lock_release(ice->grp_lock); 
    22352268            return; 
    22362269        } 
     
    22472280        on_check_complete(ice, check); 
    22482281        pj_log_pop_indent(); 
    2249         pj_mutex_unlock(ice->mutex); 
     2282        pj_grp_lock_release(ice->grp_lock); 
    22502283        return; 
    22512284    } 
     
    22712304        on_check_complete(ice, check); 
    22722305        pj_log_pop_indent(); 
    2273         pj_mutex_unlock(ice->mutex); 
     2306        pj_grp_lock_release(ice->grp_lock); 
    22742307        return; 
    22752308    } 
     
    23042337                        PJNATH_ESTUNNOMAPPEDADDR); 
    23052338        on_check_complete(ice, check); 
    2306         pj_mutex_unlock(ice->mutex); 
     2339        pj_grp_lock_release(ice->grp_lock); 
    23072340        return; 
    23082341    } 
     
    23522385                            status); 
    23532386            on_check_complete(ice, check); 
    2354             pj_mutex_unlock(ice->mutex); 
     2387            pj_grp_lock_release(ice->grp_lock); 
    23552388            return; 
    23562389        } 
     
    24122445    if (on_check_complete(ice, check)) { 
    24132446        /* ICE complete! */ 
    2414         pj_mutex_unlock(ice->mutex); 
     2447        pj_grp_lock_release(ice->grp_lock); 
    24152448        return; 
    24162449    } 
    24172450 
    2418     pj_mutex_unlock(ice->mutex); 
     2451    pj_grp_lock_release(ice->grp_lock); 
    24192452} 
    24202453 
     
    24572490    ice = sd->ice; 
    24582491 
    2459     pj_mutex_lock(ice->mutex); 
     2492    pj_grp_lock_acquire(ice->grp_lock); 
     2493 
     2494    if (ice->is_destroying) { 
     2495        pj_grp_lock_release(ice->grp_lock); 
     2496        return PJ_EINVALIDOP; 
     2497    } 
    24602498 
    24612499    /* 
     
    24722510    if (prio_attr == NULL) { 
    24732511        LOG5((ice->obj_name, "Received Binding request with no PRIORITY")); 
    2474         pj_mutex_unlock(ice->mutex); 
     2512        pj_grp_lock_release(ice->grp_lock); 
    24752513        return PJ_SUCCESS; 
    24762514    } 
     
    25172555                                    NULL, token, PJ_TRUE,  
    25182556                                    src_addr, src_addr_len); 
    2519             pj_mutex_unlock(ice->mutex); 
     2557            pj_grp_lock_release(ice->grp_lock); 
    25202558            return PJ_SUCCESS; 
    25212559        } 
     
    25292567                                    NULL, token, PJ_TRUE,  
    25302568                                    src_addr, src_addr_len); 
    2531             pj_mutex_unlock(ice->mutex); 
     2569            pj_grp_lock_release(ice->grp_lock); 
    25322570            return PJ_SUCCESS; 
    25332571        } else { 
     
    25442582    status = pj_stun_session_create_res(sess, rdata, 0, NULL, &tdata); 
    25452583    if (status != PJ_SUCCESS) { 
    2546         pj_mutex_unlock(ice->mutex); 
     2584        pj_grp_lock_release(ice->grp_lock); 
    25472585        return status; 
    25482586    } 
     
    25962634    } 
    25972635 
    2598     pj_mutex_unlock(ice->mutex); 
     2636    pj_grp_lock_release(ice->grp_lock); 
    25992637    return PJ_SUCCESS; 
    26002638} 
     
    28852923    } 
    28862924 
    2887     pj_mutex_lock(ice->mutex); 
     2925    pj_grp_lock_acquire(ice->grp_lock); 
     2926 
     2927    if (ice->is_destroying) { 
     2928        pj_grp_lock_release(ice->grp_lock); 
     2929        return PJ_EINVALIDOP; 
     2930    } 
    28882931 
    28892932    comp = find_comp(ice, comp_id); 
    28902933    if (comp == NULL) { 
    28912934        status = PJNATH_EICEINCOMPID; 
    2892         pj_mutex_unlock(ice->mutex); 
     2935        pj_grp_lock_release(ice->grp_lock); 
    28932936        goto on_return; 
    28942937    } 
     
    28962939    if (comp->valid_check == NULL) { 
    28972940        status = PJNATH_EICEINPROGRESS; 
    2898         pj_mutex_unlock(ice->mutex); 
     2941        pj_grp_lock_release(ice->grp_lock); 
    28992942        goto on_return; 
    29002943    } 
     
    29052948 
    29062949    /* Release the mutex now to avoid deadlock (see ticket #1451). */ 
    2907     pj_mutex_unlock(ice->mutex); 
     2950    pj_grp_lock_release(ice->grp_lock); 
     2951 
     2952    PJ_RACE_ME(5); 
    29082953 
    29092954    status = (*ice->cb.on_tx_pkt)(ice, comp_id, transport_id,  
     
    29322977    PJ_ASSERT_RETURN(ice, PJ_EINVAL); 
    29332978 
    2934     pj_mutex_lock(ice->mutex); 
     2979    pj_grp_lock_acquire(ice->grp_lock); 
     2980 
     2981    if (ice->is_destroying) { 
     2982        pj_grp_lock_release(ice->grp_lock); 
     2983        return PJ_EINVALIDOP; 
     2984    } 
    29352985 
    29362986    comp = find_comp(ice, comp_id); 
    29372987    if (comp == NULL) { 
    2938         pj_mutex_unlock(ice->mutex); 
     2988        pj_grp_lock_release(ice->grp_lock); 
    29392989        return PJNATH_EICEINCOMPID; 
    29402990    } 
     
    29492999    if (msg_data == NULL) { 
    29503000        pj_assert(!"Invalid transport ID"); 
    2951         pj_mutex_unlock(ice->mutex); 
     3001        pj_grp_lock_release(ice->grp_lock); 
    29523002        return PJ_EINVAL; 
    29533003    } 
     
    29693019                  ice->tmp.errmsg)); 
    29703020        } 
    2971         pj_mutex_unlock(ice->mutex); 
     3021        pj_grp_lock_release(ice->grp_lock); 
    29723022    } else { 
    29733023        /* Not a STUN packet. Call application's callback instead, but release 
    29743024         * the mutex now or otherwise we may get deadlock. 
    29753025         */ 
    2976         pj_mutex_unlock(ice->mutex); 
     3026        pj_grp_lock_release(ice->grp_lock); 
     3027 
     3028        PJ_RACE_ME(5); 
    29773029 
    29783030        (*ice->cb.on_rx_data)(ice, comp_id, transport_id, pkt, pkt_size,  
Note: See TracChangeset for help on using the changeset viewer.