Changeset 671


Ignore:
Timestamp:
Aug 10, 2006 9:44:26 PM (16 years ago)
Author:
bennylp
Message:

Attempt to fix the race condition in dialog locking.

Location:
pjproject/trunk/pjsip
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsip/sip_dialog.h

    r622 r671  
    109109    char                obj_name[PJ_MAX_OBJ_NAME];  /**< Standard id.       */ 
    110110    pj_pool_t          *pool;       /**< Dialog's pool.                     */ 
    111     pj_mutex_t         *mutex;      /**< Dialog's mutex. Do not call!! 
     111    pj_mutex_t         *mutex_;     /**< Dialog's mutex. Do not call!! 
    112112                                         Use pjsip_dlg_inc_lock() instead!  */ 
    113113    pjsip_user_agent   *ua;         /**< User agent instance.               */ 
  • pjproject/trunk/pjsip/include/pjsip/sip_ua_layer.h

    r515 r671  
    8080PJ_DECL(pjsip_user_agent*) pjsip_ua_instance(void); 
    8181 
     82 
     83/** 
     84 * Lock the dialog's hash table. This function is normally called by 
     85 * dialog code only. 
     86 * 
     87 * @return              PJ_SUCCESS on success or the appropriate error code. 
     88 */ 
     89PJ_DECL(pj_status_t) pjsip_ua_lock_dlg_table(void); 
     90 
     91 
     92/** 
     93 * Unlock the dialog's hash table. This function is normally called by 
     94 * dialog code only. 
     95 * 
     96 * @return              PJ_SUCCESS on success or the appropriate error code. 
     97 */ 
     98PJ_DECL(pj_status_t) pjsip_ua_unlock_dlg_table(void); 
     99 
     100 
    82101/** 
    83102 * Destroy the user agent layer. 
  • pjproject/trunk/pjsip/src/pjsip-simple/evsub.c

    r612 r671  
    669669 
    670670 
     671    /* Must lock dialog before using pool etc. */ 
     672    pjsip_dlg_inc_lock(dlg); 
     673 
    671674    /* Init attributes: */ 
    672675 
     
    715718 
    716719    status = pjsip_dlg_add_usage(dlg, &mod_evsub.mod, dlgsub_head); 
    717     if (status != PJ_SUCCESS) 
     720    if (status != PJ_SUCCESS) { 
     721        pjsip_dlg_dec_lock(dlg); 
    718722        return status; 
     723    } 
    719724 
    720725 
     
    724729 
    725730    *p_evsub = sub; 
     731    pjsip_dlg_dec_lock(dlg); 
    726732 
    727733    return PJ_SUCCESS; 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r657 r671  
    436436    PJ_ASSERT_RETURN(dlg && p_inv, PJ_EINVAL); 
    437437 
     438    /* Must lock dialog first */ 
     439    pjsip_dlg_inc_lock(dlg); 
     440 
    438441    /* Normalize options */ 
    439442    if (options & PJSIP_INV_REQUIRE_100REL) 
     
    445448    /* Create the session */ 
    446449    inv = pj_pool_zalloc(dlg->pool, sizeof(pjsip_inv_session)); 
    447     PJ_ASSERT_RETURN(inv != NULL, PJ_ENOMEM); 
     450    pj_assert(inv != NULL); 
    448451 
    449452    inv->pool = dlg->pool; 
     
    462465        status = pjmedia_sdp_neg_create_w_local_offer(dlg->pool, local_sdp, 
    463466                                                      &inv->neg); 
    464         if (status != PJ_SUCCESS) 
     467        if (status != PJ_SUCCESS) { 
     468            pjsip_dlg_dec_lock(dlg); 
    465469            return status; 
     470        } 
    466471    } 
    467472 
    468473    /* Register invite as dialog usage. */ 
    469474    status = pjsip_dlg_add_usage(dlg, &mod_inv.mod, inv); 
    470     if (status != PJ_SUCCESS) 
     475    if (status != PJ_SUCCESS) { 
     476        pjsip_dlg_dec_lock(dlg); 
    471477        return status; 
     478    } 
    472479 
    473480    /* Increment dialog session */ 
     
    476483    /* Done */ 
    477484    *p_inv = inv; 
     485 
     486    pjsip_dlg_dec_lock(dlg); 
    478487 
    479488    PJ_LOG(5,(inv->obj_name, "UAC invite session created for dialog %s", 
     
    841850                     PJ_EINVALIDOP); 
    842851 
     852    /* Lock dialog */ 
     853    pjsip_dlg_inc_lock(dlg); 
     854 
    843855    /* Normalize options */ 
    844856    if (options & PJSIP_INV_REQUIRE_100REL) 
     
    850862    /* Create the session */ 
    851863    inv = pj_pool_zalloc(dlg->pool, sizeof(pjsip_inv_session)); 
    852     PJ_ASSERT_RETURN(inv != NULL, PJ_ENOMEM); 
     864    pj_assert(inv != NULL); 
    853865 
    854866    inv->pool = dlg->pool; 
     
    873885            status = pjmedia_sdp_validate(rem_sdp); 
    874886 
    875         if (status != PJ_SUCCESS) 
     887        if (status != PJ_SUCCESS) { 
     888            pjsip_dlg_dec_lock(dlg); 
    876889            return status; 
     890        } 
    877891    } 
    878892 
     
    889903    } 
    890904 
    891     if (status != PJ_SUCCESS) 
     905    if (status != PJ_SUCCESS) { 
     906        pjsip_dlg_dec_lock(dlg); 
    892907        return status; 
     908    } 
    893909 
    894910    /* Register invite as dialog usage. */ 
    895911    status = pjsip_dlg_add_usage(dlg, &mod_inv.mod, inv); 
    896     if (status != PJ_SUCCESS) 
     912    if (status != PJ_SUCCESS) { 
     913        pjsip_dlg_dec_lock(dlg); 
    897914        return status; 
     915    } 
    898916 
    899917    /* Increment session in the dialog. */ 
     
    910928 
    911929    /* Done */ 
     930    pjsip_dlg_dec_lock(dlg); 
    912931    *p_inv = inv; 
    913932 
  • pjproject/trunk/pjsip/src/pjsip/sip_dialog.c

    r635 r671  
    8181    pj_list_init(&dlg->inv_hdr); 
    8282 
    83     status = pj_mutex_create_recursive(pool, "dlg%p", &dlg->mutex); 
     83    status = pj_mutex_create_recursive(pool, "dlg%p", &dlg->mutex_); 
    8484    if (status != PJ_SUCCESS) 
    8585        goto on_error; 
     
    9090 
    9191on_error: 
    92     if (dlg->mutex) 
    93         pj_mutex_destroy(dlg->mutex); 
     92    if (dlg->mutex_) 
     93        pj_mutex_destroy(dlg->mutex_); 
    9494    pjsip_endpt_release_pool(endpt, pool); 
    9595    return status; 
     
    9898static void destroy_dialog( pjsip_dialog *dlg ) 
    9999{ 
    100     if (dlg->mutex) 
    101         pj_mutex_destroy(dlg->mutex); 
     100    if (dlg->mutex_) { 
     101        pj_mutex_destroy(dlg->mutex_); 
     102        dlg->mutex_ = NULL; 
     103    } 
    102104    pjsip_endpt_release_pool(dlg->endpt, dlg->pool); 
    103105} 
     
    607609 
    608610    /* Destroy this dialog. */ 
    609     pj_mutex_destroy(dlg->mutex); 
    610     pjsip_endpt_release_pool(dlg->endpt, dlg->pool); 
     611    destroy_dialog(dlg); 
    611612 
    612613    return PJ_SUCCESS; 
     
    639640    PJ_ASSERT_RETURN(dlg, PJ_EINVAL); 
    640641 
    641     pj_mutex_lock(dlg->mutex); 
     642    pjsip_dlg_inc_lock(dlg); 
    642643 
    643644    /* Clear route set. */ 
     
    645646 
    646647    if (!route_set) { 
    647         pj_mutex_unlock(dlg->mutex); 
     648        pjsip_dlg_dec_lock(dlg); 
    648649        return PJ_SUCCESS; 
    649650    } 
     
    659660    } 
    660661 
    661     pj_mutex_unlock(dlg->mutex); 
    662  
     662    pjsip_dlg_dec_lock(dlg); 
    663663    return PJ_SUCCESS; 
    664664} 
     
    673673    PJ_ASSERT_RETURN(dlg && mod, PJ_EINVAL); 
    674674 
    675     pj_mutex_lock(dlg->mutex); 
     675    pjsip_dlg_inc_lock(dlg); 
    676676    ++dlg->sess_count; 
    677     pj_mutex_unlock(dlg->mutex); 
     677    pjsip_dlg_dec_lock(dlg); 
    678678 
    679679    PJ_LOG(5,(dlg->obj_name, "Session count inc to %d by %.*s", 
     
    685685/* 
    686686 * Lock dialog and increment session counter temporarily 
    687  * to prevent it from being deleted. 
     687 * to prevent it from being deleted. In addition, it must lock 
     688 * the user agent's dialog table first, to prevent deadlock. 
    688689 */ 
    689690PJ_DEF(void) pjsip_dlg_inc_lock(pjsip_dialog *dlg) 
    690691{ 
    691     pj_mutex_lock(dlg->mutex); 
     692    pjsip_ua_lock_dlg_table(); 
     693 
     694    pj_mutex_lock(dlg->mutex_); 
    692695    dlg->sess_count++; 
     696 
     697    pjsip_ua_unlock_dlg_table(); 
    693698} 
    694699 
     
    700705PJ_DEF(void) pjsip_dlg_dec_lock(pjsip_dialog *dlg) 
    701706{ 
     707    pjsip_ua_lock_dlg_table(); 
     708 
    702709    pj_assert(dlg->sess_count > 0); 
    703710    --dlg->sess_count; 
    704711 
    705712    if (dlg->sess_count==0 && dlg->tsx_count==0) { 
    706         pj_mutex_unlock(dlg->mutex); 
    707         pj_mutex_lock(dlg->mutex); 
     713        pj_mutex_unlock(dlg->mutex_); 
     714        pj_mutex_lock(dlg->mutex_); 
    708715        unregister_and_destroy_dialog(dlg); 
    709716    } else { 
    710         pj_mutex_unlock(dlg->mutex); 
    711     } 
     717        pj_mutex_unlock(dlg->mutex_); 
     718    } 
     719 
     720    pjsip_ua_unlock_dlg_table(); 
    712721} 
    713722 
     
    725734              dlg->sess_count-1, (int)mod->name.slen, mod->name.ptr)); 
    726735 
    727     pj_mutex_lock(dlg->mutex); 
     736    pjsip_dlg_inc_lock(dlg); 
     737    --dlg->sess_count; 
    728738    pjsip_dlg_dec_lock(dlg); 
    729739 
     
    749759              (int)mod->name.slen, mod->name.ptr, mod_data)); 
    750760 
    751     pj_mutex_lock(dlg->mutex); 
     761    pjsip_dlg_inc_lock(dlg); 
    752762 
    753763    /* Usages are sorted on priority, lowest number first. 
     
    758768        if (dlg->usage[index] == mod) { 
    759769            pj_assert(!"This module is already registered"); 
    760             pj_mutex_unlock(dlg->mutex); 
     770            pjsip_dlg_dec_lock(dlg); 
    761771            return PJSIP_ETYPEEXISTS; 
    762772        } 
     
    778788    ++dlg->usage_cnt; 
    779789 
    780     pj_mutex_unlock(dlg->mutex); 
     790    pjsip_dlg_dec_lock(dlg); 
    781791 
    782792    return PJ_SUCCESS; 
     
    897907 
    898908    /* Lock dialog. */ 
    899     pj_mutex_lock(dlg->mutex); 
     909    pjsip_dlg_inc_lock(dlg); 
    900910 
    901911    /* Use outgoing CSeq and increment it by one. */ 
     
    922932 
    923933    /* Unlock dialog. */ 
    924     pj_mutex_unlock(dlg->mutex); 
     934    pjsip_dlg_dec_lock(dlg); 
    925935 
    926936    *p_tdata = tdata; 
     
    11141124 
    11151125    /* Lock the dialog. */ 
    1116     pj_mutex_lock(dlg->mutex); 
     1126    pjsip_dlg_inc_lock(dlg); 
    11171127 
    11181128    dlg_beautify_response(dlg, st_code, tdata); 
    11191129 
    11201130    /* Unlock the dialog. */ 
    1121     pj_mutex_unlock(dlg->mutex); 
     1131    pjsip_dlg_dec_lock(dlg); 
    11221132 
    11231133    /* Done. */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_ua_layer.c

    r624 r671  
    210210 
    211211 
     212/** 
     213 * Lock the dialog's hash table. This function is normally called by 
     214 * dialog code only. 
     215 * 
     216 * @return              PJ_SUCCESS on success or the appropriate error code. 
     217 */ 
     218PJ_DEF(pj_status_t) pjsip_ua_lock_dlg_table(void) 
     219{ 
     220    return pj_mutex_lock(mod_ua.mutex); 
     221} 
     222 
     223 
     224/** 
     225 * Unlock the dialog's hash table. This function is normally called by 
     226 * dialog code only. 
     227 * 
     228 * @return              PJ_SUCCESS on success or the appropriate error code. 
     229 */ 
     230PJ_DEF(pj_status_t) pjsip_ua_unlock_dlg_table(void) 
     231{ 
     232    return pj_mutex_unlock(mod_ua.mutex); 
     233} 
     234 
     235 
    212236/* 
    213237 * Get the endpoint where this UA is currently registered. 
     
    562586    rdata->endpt_info.mod_data[mod_ua.mod.id] = dlg; 
    563587 
     588    /* Lock the dialog */ 
     589    pjsip_dlg_inc_lock(dlg); 
     590 
    564591    /* Done processing in the UA */ 
    565592    pj_mutex_unlock(mod_ua.mutex); 
     
    567594    /* Pass to dialog. */ 
    568595    pjsip_dlg_on_rx_request(dlg, rdata); 
     596 
     597    /* Unlock the dialog. This may destroy the dialog */ 
     598    pjsip_dlg_dec_lock(dlg); 
    569599 
    570600    /* Report as handled. */ 
     
    591621     */ 
    592622 
     623    /* Lock user agent dlg table before we're doing anything. */ 
     624    pj_mutex_lock(mod_ua.mutex); 
     625 
    593626    /* Check if transaction is present. */ 
    594627    tsx = pjsip_rdata_get_tsx(rdata); 
     
    596629        /* Check if dialog is present in the transaction. */ 
    597630        dlg = pjsip_tsx_get_dlg(tsx); 
    598         if (!dlg) 
     631        if (!dlg) { 
     632            /* Unlock dialog hash table. */ 
     633            pj_mutex_unlock(mod_ua.mutex); 
    599634            return PJ_FALSE; 
     635        } 
    600636 
    601637        /* Get the dialog set. */ 
     
    621657             * or a very late response. 
    622658             */ 
     659            /* Unlock dialog hash table. */ 
     660            pj_mutex_unlock(mod_ua.mutex); 
    623661            return PJ_FALSE; 
    624662        } 
    625663 
    626         /* Lock user agent before accessing the hash table. */ 
    627         pj_mutex_lock(mod_ua.mutex); 
    628664 
    629665        /* Get the dialog set. */ 
     
    633669                              NULL); 
    634670 
    635         /* Done with accessing the hash table. */ 
    636         pj_mutex_unlock(mod_ua.mutex); 
    637  
    638671        if (!dlg_set) { 
     672            /* Unlock dialog hash table. */ 
     673            pj_mutex_unlock(mod_ua.mutex); 
     674 
    639675            /* Strayed 2xx response!! */ 
    640676            PJ_LOG(4,(THIS_FILE,  
     
    666702        int st_code = rdata->msg_info.msg->line.status.code; 
    667703        pj_str_t *to_tag = &rdata->msg_info.to->tag; 
    668  
    669         /* Must hold UA mutex before accessing dialog set. */ 
    670         pj_mutex_lock(mod_ua.mutex); 
    671704 
    672705        dlg = dlg_set->dlg_list.next; 
     
    734767        } 
    735768 
    736         /* Done with the dialog set. */ 
    737         pj_mutex_unlock(mod_ua.mutex); 
    738  
    739769    } else { 
    740770        /* Either this is a non-INVITE response, or subsequent INVITE 
     
    752782    rdata->endpt_info.mod_data[mod_ua.mod.id] = dlg; 
    753783 
     784    /* Acquire lock to the dialog. */ 
     785    pjsip_dlg_inc_lock(dlg); 
     786 
     787    /* Unlock dialog hash table. */ 
     788    pj_mutex_unlock(mod_ua.mutex); 
     789 
    754790    /* Pass the response to the dialog. */ 
    755791    pjsip_dlg_on_rx_response(dlg, rdata); 
     792 
     793    /* Unlock the dialog. This may destroy the dialog. */ 
     794    pjsip_dlg_dec_lock(dlg); 
    756795 
    757796    /* Done. */ 
Note: See TracChangeset for help on using the changeset viewer.