Changeset 6037


Ignore:
Timestamp:
Jul 10, 2019 7:15:08 AM (3 years ago)
Author:
riza
Message:

Close #2211: Use group lock for SIP dialog.

Location:
pjproject/trunk/pjsip
Files:
3 edited

Legend:

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

    r5456 r6037  
    142142    char                obj_name[PJ_MAX_OBJ_NAME];  /**< Standard id.       */ 
    143143    pj_pool_t          *pool;       /**< Dialog's pool.                     */ 
    144     pj_mutex_t         *mutex_;     /**< Dialog's mutex. Do not call!! 
    145                                          Use pjsip_dlg_inc_lock() instead!  */ 
    146144    pjsip_user_agent   *ua;         /**< User agent instance.               */ 
    147145    pjsip_endpoint     *endpt;      /**< Endpoint instance.                 */ 
     146    pj_grp_lock_t      *grp_lock_;  /**< Dialog's grp lock. Do not call!! 
     147                                         Use pjsip_dlg_inc_lock() instead!  */ 
    148148 
    149149    /** The dialog set which this dialog belongs (opaque type). */ 
     
    192192    const void         *via_tp;     /**< Via transport.                     */ 
    193193}; 
     194 
     195/** 
     196 * The parameter for \a pjsip_dlg_create_uac2(). 
     197 */ 
     198typedef struct pjsip_dlg_create_uac_param { 
     199    /** 
     200     * The user agent module instance. 
     201     */ 
     202    pjsip_user_agent *ua; 
     203 
     204    /** 
     205     * Dialog local URI (i.e. From header). 
     206     */ 
     207    pj_str_t local_uri; 
     208 
     209    /** 
     210     * Optional dialog local Contact to be put as Contact header value, 
     211     * hence the format must follow RFC 3261 Section 20.10: 
     212     * When the header field value contains a display name, the URI including 
     213     * all URI parameters is enclosed in "<" and ">".  If no "<" and ">" are 
     214     * present, all parameters after the URI are header parameters, not 
     215     * URI parameters.  The display name can be tokens, or a quoted string, 
     216     * if a larger character set is desired. If this argument is NULL, 
     217     * the Contact will be taken from the local URI. 
     218     */ 
     219    pj_str_t local_contact; 
     220 
     221    /** 
     222     * Dialog remote URI (i.e. To header). 
     223     */ 
     224    pj_str_t remote_uri; 
     225 
     226    /** 
     227     * Optional initial remote target. If this argument is NULL, the initial  
     228     * target will be set to remote URI. 
     229     */ 
     230    pj_str_t target; 
     231 
     232    /** 
     233     * Optional group lock to use by this dialog. If the value is NULL,  
     234     * the dialog will create its own group lock. 
     235     */ 
     236    pj_grp_lock_t *grp_lock; 
     237 
     238} pjsip_dlg_create_uac_param; 
    194239 
    195240 
     
    249294                                           pjsip_dialog **p_dlg); 
    250295 
     296/** 
     297 * Variant of pjsip_dlg_create_uac() with additional parameter to specify 
     298 * the group lock to use. Group lock can be used to synchronize locking 
     299 * among several objects to prevent deadlock, and to synchronize the 
     300 * lifetime of objects sharing the same group lock. 
     301 * 
     302 * See \a pjsip_dlg_create_uac() for general info about this function. 
     303 * 
     304 * @param param             The parameter, refer to 
     305 *                          \a pjsip_dlg_create_uac_param 
     306 * @param p_dlg             Pointer to receive the dialog. 
     307 * 
     308 * @return                  PJ_SUCCESS on success. 
     309 */ 
     310PJ_DECL(pj_status_t) pjsip_dlg_create_uac2( 
     311                                const pjsip_dlg_create_uac_param *create_param, 
     312                                pjsip_dialog **p_dlg); 
     313 
    251314 
    252315#if !DEPRECATED_FOR_TICKET_1902 
     
    539602PJ_DECL(void) pjsip_dlg_dec_lock( pjsip_dialog *dlg ); 
    540603 
     604/** 
     605 * Get the group lock for the SIP dialog. Note that prior to calling this 
     606 * method, it is recommended to hold reference to the dialog 
     607 * (e.g: call #pjsip_dlg_inc_session() or #pjsip_dlg_inc_lock()). 
     608 * 
     609 * @param dlg               The dialog. 
     610 * 
     611 * @return                  The group lock. 
     612 */ 
     613PJ_DECL(pj_grp_lock_t *) pjsip_dlg_get_lock( pjsip_dialog *dlg ); 
     614 
    541615 
    542616/** 
  • pjproject/trunk/pjsip/src/pjsip/sip_dialog.c

    r5689 r6037  
    6262} 
    6363 
     64static void dlg_on_destroy( void *arg ) 
     65{ 
     66    pjsip_dialog *dlg = (pjsip_dialog *)arg; 
     67 
     68    PJ_LOG(5,(dlg->obj_name, "Dialog destroyed!")); 
     69 
     70    pjsip_endpt_release_pool(dlg->endpt, dlg->pool); 
     71} 
     72 
    6473static pj_status_t create_dialog( pjsip_user_agent *ua, 
     74                                  pj_grp_lock_t *grp_lock, 
    6575                                  pjsip_dialog **p_dlg) 
    6676{ 
     
    99109        goto on_error; 
    100110 
    101     status = pj_mutex_create_recursive(pool, dlg->obj_name, &dlg->mutex_); 
    102     if (status != PJ_SUCCESS) 
    103         goto on_error; 
     111    if (grp_lock) { 
     112        dlg->grp_lock_ = grp_lock; 
     113    } else { 
     114        status = pj_grp_lock_create(pool, NULL, &dlg->grp_lock_); 
     115        if (status != PJ_SUCCESS) { 
     116            goto on_error; 
     117        } 
     118    } 
     119 
     120    pj_grp_lock_add_ref(dlg->grp_lock_); 
     121    pj_grp_lock_add_handler(dlg->grp_lock_, pool, dlg, &dlg_on_destroy); 
    104122 
    105123    pjsip_target_set_init(&dlg->target_set); 
     
    109127 
    110128on_error: 
    111     if (dlg->mutex_) 
    112         pj_mutex_destroy(dlg->mutex_); 
    113129    pjsip_endpt_release_pool(endpt, pool); 
    114130    return status; 
     
    117133static void destroy_dialog( pjsip_dialog *dlg, pj_bool_t unlock_mutex ) 
    118134{ 
    119     if (dlg->mutex_) { 
    120         if (unlock_mutex) pj_mutex_unlock(dlg->mutex_); 
    121         pj_mutex_destroy(dlg->mutex_); 
    122         dlg->mutex_ = NULL; 
    123     } 
    124135    if (dlg->tp_sel.type != PJSIP_TPSELECTOR_NONE) { 
    125136        pjsip_tpselector_dec_ref(&dlg->tp_sel); 
     
    127138    } 
    128139    pjsip_auth_clt_deinit(&dlg->auth_sess); 
    129     pjsip_endpt_release_pool(dlg->endpt, dlg->pool); 
    130 } 
    131  
     140 
     141    pj_grp_lock_dec_ref(dlg->grp_lock_); 
     142 
     143    if (unlock_mutex) 
     144        pj_grp_lock_release(dlg->grp_lock_); 
     145} 
    132146 
    133147/* 
     
    141155                                          pjsip_dialog **p_dlg) 
    142156{ 
     157    PJ_ASSERT_RETURN(ua && local_uri && remote_uri && p_dlg, PJ_EINVAL); 
     158 
     159    pjsip_dlg_create_uac_param create_param; 
     160    pj_bzero(&create_param, sizeof(create_param)); 
     161 
     162    create_param.ua = ua; 
     163    create_param.local_uri = *local_uri; 
     164    create_param.remote_uri = *remote_uri; 
     165    if (local_contact) 
     166        create_param.local_contact = *local_contact; 
     167 
     168    if (target) 
     169        create_param.target = *target; 
     170 
     171    return pjsip_dlg_create_uac2(&create_param, p_dlg); 
     172} 
     173 
     174PJ_DEF(pj_status_t) pjsip_dlg_create_uac2( 
     175                                const pjsip_dlg_create_uac_param *create_param, 
     176                                pjsip_dialog **p_dlg) 
     177{ 
    143178    pj_status_t status; 
    144179    pj_str_t tmp; 
     
    146181 
    147182    /* Check arguments. */ 
    148     PJ_ASSERT_RETURN(ua && local_uri && remote_uri && p_dlg, PJ_EINVAL); 
     183    PJ_ASSERT_RETURN(create_param->ua && create_param->local_uri.slen && 
     184                     create_param->remote_uri.slen && p_dlg, PJ_EINVAL); 
    149185 
    150186    /* Create dialog instance. */ 
    151     status = create_dialog(ua, &dlg); 
     187    status = create_dialog(create_param->ua, create_param->grp_lock, &dlg); 
    152188    if (status != PJ_SUCCESS) 
    153189        return status; 
    154190 
    155191    /* Parse target. */ 
    156     pj_strdup_with_null(dlg->pool, &tmp, target ? target : remote_uri); 
     192    pj_strdup_with_null(dlg->pool, &tmp, create_param->target.slen ? 
     193                        &create_param->target : &create_param->remote_uri); 
    157194    dlg->target = pjsip_parse_uri(dlg->pool, tmp.ptr, tmp.slen, 0); 
    158195    if (!dlg->target) { 
     
    204241    /* Init local info. */ 
    205242    dlg->local.info = pjsip_from_hdr_create(dlg->pool); 
    206     pj_strdup_with_null(dlg->pool, &dlg->local.info_str, local_uri); 
     243    pj_strdup_with_null(dlg->pool, &dlg->local.info_str, 
     244                        &create_param->local_uri); 
    207245    dlg->local.info->uri = pjsip_parse_uri(dlg->pool, 
    208246                                           dlg->local.info_str.ptr, 
     
    226264    /* Init local contact. */ 
    227265    pj_strdup_with_null(dlg->pool, &tmp, 
    228                         local_contact ? local_contact : local_uri); 
     266                    create_param->local_contact.slen ? 
     267                    &create_param->local_contact : &create_param->local_uri); 
    229268    dlg->local.contact = (pjsip_contact_hdr*) 
    230269                         pjsip_parse_hdr(dlg->pool, &HCONTACT, tmp.ptr, 
     
    237276    /* Init remote info. */ 
    238277    dlg->remote.info = pjsip_to_hdr_create(dlg->pool); 
    239     pj_strdup_with_null(dlg->pool, &dlg->remote.info_str, remote_uri); 
     278    pj_strdup_with_null(dlg->pool, &dlg->remote.info_str, 
     279                        &create_param->remote_uri); 
    240280    dlg->remote.info->uri = pjsip_parse_uri(dlg->pool, 
    241281                                            dlg->remote.info_str.ptr, 
     
    293333 
    294334    /* Register this dialog to user agent. */ 
    295     status = pjsip_ua_register_dlg( ua, dlg ); 
     335    status = pjsip_ua_register_dlg( create_param->ua, dlg ); 
    296336    if (status != PJ_SUCCESS) 
    297337        goto on_error; 
    298338 
    299  
    300339    /* Done! */ 
    301340    *p_dlg = dlg; 
    302  
    303341 
    304342    PJ_LOG(5,(dlg->obj_name, "UAC dialog created")); 
     
    350388 
    351389    /* Create dialog instance. */ 
    352     status = create_dialog(ua, &dlg); 
     390    status = create_dialog(ua, NULL, &dlg); 
    353391    if (status != PJ_SUCCESS) 
    354392        return status; 
     
    565603        destroy_dialog(dlg, PJ_FALSE); 
    566604    } 
    567      
     605 
    568606    return status; 
    569607} 
     
    681719 
    682720    /* Create the dialog. */ 
    683     status = create_dialog((pjsip_user_agent*)first_dlg->ua, &dlg); 
     721    status = create_dialog((pjsip_user_agent*)first_dlg->ua, NULL, &dlg); 
    684722    if (status != PJ_SUCCESS) 
    685723        return status; 
     
    772810 
    773811/* 
    774  * Destroy dialog. 
     812 * Unregister and destroy dialog. 
    775813 */ 
    776814static pj_status_t unregister_and_destroy_dialog( pjsip_dialog *dlg, 
     
    797835    } 
    798836 
    799     /* Log */ 
    800     PJ_LOG(5,(dlg->obj_name, "Dialog destroyed")); 
    801  
    802837    /* Destroy this dialog. */ 
    803838    destroy_dialog(dlg, unlock_mutex); 
     
    879914 
    880915/* 
    881  * Lock dialog and increment session counter temporarily 
     916 * Lock dialog and increment session count temporarily 
    882917 * to prevent it from being deleted. In addition, it must lock 
    883918 * the user agent's dialog table first, to prevent deadlock. 
     
    888923              dlg->sess_count)); 
    889924 
    890     pj_mutex_lock(dlg->mutex_); 
     925    pj_grp_lock_acquire(dlg->grp_lock_); 
    891926    dlg->sess_count++; 
    892927 
     
    895930} 
    896931 
    897 /* Try to acquire dialog's mutex, but bail out if mutex can not be 
     932/* Try to acquire dialog's group lock, but bail out if group lock can not be 
    898933 * acquired immediately. 
    899934 */ 
     
    905940              dlg->sess_count)); 
    906941 
    907     status = pj_mutex_trylock(dlg->mutex_); 
     942    status = pj_grp_lock_tryacquire(dlg->grp_lock_); 
    908943    if (status != PJ_SUCCESS) { 
    909944        PJ_LOG(6,(dlg->obj_name, "pjsip_dlg_try_inc_lock() failed")); 
     
    921956 
    922957/* 
    923  * Unlock dialog and decrement session counter. 
     958 * Unlock dialog and decrement reference counter. 
    924959 * It may delete the dialog! 
    925960 */ 
     
    935970 
    936971    if (dlg->sess_count==0 && dlg->tsx_count==0) { 
    937         pj_mutex_unlock(dlg->mutex_); 
    938         pj_mutex_lock(dlg->mutex_); 
    939         /* We are holding the dialog mutex here, so before we destroy 
     972        pj_grp_lock_release(dlg->grp_lock_); 
     973        pj_grp_lock_acquire(dlg->grp_lock_); 
     974        /* We are holding the dialog group lock here, so before we destroy 
    940975         * the dialog, make sure that we unlock it first to avoid 
    941976         * undefined behaviour on some platforms. See ticket #1886. 
     
    943978        unregister_and_destroy_dialog(dlg, PJ_TRUE); 
    944979    } else { 
    945         pj_mutex_unlock(dlg->mutex_); 
     980        pj_grp_lock_release(dlg->grp_lock_); 
    946981    } 
    947982 
     
    950985 
    951986 
    952  
    953 /* 
    954  * Decrement session counter. 
     987/* 
     988 * Decrement session count. 
    955989 */ 
    956990PJ_DEF(pj_status_t) pjsip_dlg_dec_session( pjsip_dialog *dlg, 
     
    9701004    pj_log_pop_indent(); 
    9711005    return PJ_SUCCESS; 
     1006} 
     1007 
     1008PJ_DEF(pj_grp_lock_t *) pjsip_dlg_get_lock(pjsip_dialog *dlg) 
     1009{ 
     1010    PJ_ASSERT_RETURN(dlg, NULL); 
     1011    return dlg->grp_lock_; 
    9721012} 
    9731013 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r6004 r6037  
    11191119             * https://trac.pjsip.org/repos/ticket/1737 
    11201120             */ 
    1121             ++dlg->sess_count; 
     1121            pjsip_dlg_inc_session(dlg, &pjsua_var.mod); 
    11221122            pjsip_dlg_dec_lock(dlg); 
    11231123        } 
     
    11271127        if (dlg) { 
    11281128            pjsip_dlg_inc_lock(dlg); 
    1129             --dlg->sess_count; 
     1129            pjsip_dlg_dec_session(dlg, &pjsua_var.mod); 
    11301130        } 
    11311131        if (has_pjsua_lock) 
Note: See TracChangeset for help on using the changeset viewer.