Ignore:
Timestamp:
Mar 5, 2013 11:59:54 AM (11 years ago)
Author:
bennylp
Message:

Implementation of Re #1628: Modify SIP transaction to use group lock to avoid deadlock etc.

File:
1 edited

Legend:

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

    r4208 r4420  
    2828#include <pj/pool.h> 
    2929#include <pj/os.h> 
     30#include <pj/rand.h> 
    3031#include <pj/string.h> 
    3132#include <pj/assert.h> 
     
    9192}; 
    9293 
    93 /* Thread Local Storage ID for transaction lock */ 
    94 static long pjsip_tsx_lock_tls_id; 
    95  
    9694/* Transaction state names */ 
    9795static const char *state_str[] =  
     
    123121    TSX_HAS_RESOLVED_SERVER     = 16, 
    124122}; 
    125  
    126 /* Transaction lock. */ 
    127 typedef struct tsx_lock_data { 
    128     struct tsx_lock_data *prev; 
    129     pjsip_transaction    *tsx; 
    130     int                   is_alive; 
    131 } tsx_lock_data; 
    132  
    133123 
    134124/* Timer timeout value constants */ 
     
    149139 
    150140/* Prototypes. */ 
    151 static void        lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck); 
    152 static pj_status_t unlock_tsx( pjsip_transaction *tsx,  
    153                                struct tsx_lock_data *lck); 
    154141static pj_status_t tsx_on_state_null(           pjsip_transaction *tsx,  
    155142                                                pjsip_event *event); 
     
    179166                                       const pjsip_transport_state_info *info); 
    180167static pj_status_t tsx_create( pjsip_module *tsx_user, 
     168                               pj_grp_lock_t *grp_lock, 
    181169                               pjsip_transaction **p_tsx); 
    182 static pj_status_t tsx_destroy( pjsip_transaction *tsx ); 
     170static void        tsx_on_destroy(void *arg); 
     171static pj_status_t tsx_shutdown( pjsip_transaction *tsx ); 
    183172static void        tsx_resched_retransmission( pjsip_transaction *tsx ); 
    184173static pj_status_t tsx_retransmit( pjsip_transaction *tsx, int resched); 
     
    271260{ 
    272261#define SEPARATOR   '$' 
    273     char *key, *p, *end; 
     262    char *key, *p; 
    274263    int len; 
    275264    pj_size_t len_required; 
    276     pjsip_uri *req_uri; 
    277265    pj_str_t *host; 
    278266 
     
    284272 
    285273    host = &rdata->msg_info.via->sent_by.host; 
    286     req_uri = (pjsip_uri*)rdata->msg_info.msg->line.req.uri; 
    287274 
    288275    /* Calculate length required. */ 
     
    294281                   16;                      /* Separator+Allowance. */ 
    295282    key = p = (char*) pj_pool_alloc(pool, len_required); 
    296     end = p + len_required; 
    297283 
    298284    /* Add role. */ 
     
    452438    timeout_timer_val = td_timer_val; 
    453439 
    454     /* Initialize TLS ID for transaction lock. */ 
    455     status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id); 
    456     if (status != PJ_SUCCESS) 
    457         return status; 
    458  
    459     pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL); 
    460  
    461440    /* 
    462441     * Initialize transaction layer structure. 
     
    483462    } 
    484463 
    485     /* Create mutex. */ 
     464    /* Create group lock. */ 
    486465    status = pj_mutex_create_recursive(pool, "tsxlayer", &mod_tsx_layer.mutex); 
    487466    if (status != PJ_SUCCESS) { 
     
    666645     */ 
    667646    PJ_TODO(FIX_RACE_CONDITION_HERE); 
     647    PJ_RACE_ME(5); 
     648 
    668649    if (tsx && lock) 
    669         pj_mutex_lock(tsx->mutex); 
     650        pj_grp_lock_acquire(tsx->grp_lock); 
    670651 
    671652    return tsx; 
     
    712693            pjsip_tsx_terminate(tsx, PJSIP_SC_SERVICE_UNAVAILABLE); 
    713694            mod_tsx_layer_unregister_tsx(tsx); 
    714             tsx_destroy(tsx); 
     695            tsx_shutdown(tsx); 
    715696        } 
    716697        it = next; 
     
    735716    /* Release pool. */ 
    736717    pjsip_endpt_release_pool(mod_tsx_layer.endpt, mod_tsx_layer.pool); 
    737  
    738     /* Free TLS */ 
    739     pj_thread_local_free(pjsip_tsx_lock_tls_id); 
    740718 
    741719    /* Mark as unregistered. */ 
     
    814792     */ 
    815793    PJ_TODO(FIX_RACE_CONDITION_HERE); 
     794    PJ_RACE_ME(5); 
    816795 
    817796    /* Pass the message to the transaction. */ 
     
    863842     */ 
    864843    PJ_TODO(FIX_RACE_CONDITION_HERE); 
     844    PJ_RACE_ME(5); 
    865845 
    866846    /* Pass the message to the transaction. */ 
     
    929909 ***************************************************************************** 
    930910 **/ 
    931 /* 
    932  * Lock transaction and set the value of Thread Local Storage. 
    933  */ 
    934 static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck) 
    935 { 
    936     struct tsx_lock_data *prev_data; 
    937  
    938     pj_mutex_lock(tsx->mutex); 
    939     prev_data = (struct tsx_lock_data *)  
    940                     pj_thread_local_get(pjsip_tsx_lock_tls_id); 
    941     lck->prev = prev_data; 
    942     lck->tsx = tsx; 
    943     lck->is_alive = 1; 
    944     pj_thread_local_set(pjsip_tsx_lock_tls_id, lck); 
    945 } 
    946  
    947  
    948 /* 
    949  * Unlock transaction. 
    950  * This will selectively unlock the mutex ONLY IF the transaction has not been  
    951  * destroyed. The function knows whether the transaction has been destroyed 
    952  * because when transaction is destroyed the is_alive flag for the transaction 
    953  * will be set to zero. 
    954  */ 
    955 static pj_status_t unlock_tsx( pjsip_transaction *tsx,  
    956                                struct tsx_lock_data *lck) 
    957 { 
    958     pj_assert( (void*)pj_thread_local_get(pjsip_tsx_lock_tls_id) == lck); 
    959     pj_assert( lck->tsx == tsx ); 
    960     pj_thread_local_set(pjsip_tsx_lock_tls_id, lck->prev); 
    961     if (lck->is_alive) 
    962         pj_mutex_unlock(tsx->mutex); 
    963  
    964     return lck->is_alive ? PJ_SUCCESS : PJSIP_ETSXDESTROYED; 
    965 } 
    966  
    967  
    968911/* Lock transaction for accessing the timeout timer only. */ 
    969912static void lock_timer(pjsip_transaction *tsx) 
     
    982925 */ 
    983926static pj_status_t tsx_create( pjsip_module *tsx_user, 
     927                               pj_grp_lock_t *grp_lock, 
    984928                               pjsip_transaction **p_tsx) 
    985929{ 
     
    1010954    tsx->timeout_timer.cb = &tsx_timer_callback; 
    1011955     
    1012     status = pj_mutex_create_recursive(pool, tsx->obj_name, &tsx->mutex); 
    1013     if (status != PJ_SUCCESS) { 
    1014         pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool); 
    1015         return status; 
    1016     } 
     956    if (grp_lock) { 
     957        tsx->grp_lock = grp_lock; 
     958    } else { 
     959        status = pj_grp_lock_create(pool, NULL, &tsx->grp_lock); 
     960        if (status != PJ_SUCCESS) { 
     961            pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool); 
     962            return status; 
     963        } 
     964    } 
     965 
     966    pj_grp_lock_add_ref(tsx->grp_lock); 
     967    pj_grp_lock_add_handler(tsx->grp_lock, tsx->pool, tsx, &tsx_on_destroy); 
    1017968 
    1018969    status = pj_mutex_create_simple(pool, tsx->obj_name, &tsx->mutex_b); 
    1019970    if (status != PJ_SUCCESS) { 
    1020         pj_mutex_destroy(tsx->mutex); 
    1021         pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool); 
     971        tsx_shutdown(tsx); 
    1022972        return status; 
    1023973    } 
     
    1027977} 
    1028978 
    1029  
    1030 /* Destroy transaction. */ 
    1031 static pj_status_t tsx_destroy( pjsip_transaction *tsx ) 
    1032 { 
    1033     struct tsx_lock_data *lck; 
    1034  
     979/* Really destroy transaction, when grp_lock reference is zero */ 
     980static void tsx_on_destroy( void *arg ) 
     981{ 
     982    pjsip_transaction *tsx = (pjsip_transaction*)arg; 
     983 
     984    PJ_LOG(5,(tsx->obj_name, "Transaction destroyed!")); 
     985 
     986    pj_mutex_destroy(tsx->mutex_b); 
     987    pjsip_endpt_release_pool(tsx->endpt, tsx->pool); 
     988} 
     989 
     990/* Shutdown transaction. */ 
     991static pj_status_t tsx_shutdown( pjsip_transaction *tsx ) 
     992{ 
    1035993    /* Release the transport */ 
    1036994    tsx_update_transport(tsx, NULL); 
    1037995 
    1038     /* Decrement reference counter in transport selector */ 
    1039     pjsip_tpselector_dec_ref(&tsx->tp_sel); 
     996    /* Decrement reference counter in transport selector, only if 
     997     * we haven't been called before */ 
     998    if (!tsx->terminating) { 
     999        pjsip_tpselector_dec_ref(&tsx->tp_sel); 
     1000    } 
    10401001 
    10411002    /* Free last transmitted message. */ 
     
    10571018    /* Clear some pending flags. */ 
    10581019    tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED | TSX_HAS_PENDING_SEND); 
     1020 
    10591021 
    10601022    /* Refuse to destroy transaction if it has pending resolving. */ 
     
    10641026        PJ_LOG(4,(tsx->obj_name, "Will destroy later because transport is " 
    10651027                                 "in progress")); 
    1066         return PJ_EBUSY; 
    1067     } 
    1068  
    1069     /* Clear TLS, so that mutex will not be unlocked */ 
    1070     lck = (struct tsx_lock_data*) pj_thread_local_get(pjsip_tsx_lock_tls_id); 
    1071     while (lck) { 
    1072         if (lck->tsx == tsx) { 
    1073             lck->is_alive = 0; 
    1074         } 
    1075         lck = lck->prev; 
    1076     } 
    1077  
    1078     pj_mutex_destroy(tsx->mutex_b); 
    1079     pj_mutex_destroy(tsx->mutex); 
    1080  
    1081     PJ_LOG(5,(tsx->obj_name, "Transaction destroyed!")); 
    1082  
    1083     pjsip_endpt_release_pool(tsx->endpt, tsx->pool); 
     1028    } 
     1029 
     1030    if (!tsx->terminating) { 
     1031        tsx->terminating = PJ_TRUE; 
     1032        pj_grp_lock_dec_ref(tsx->grp_lock); 
     1033    } 
     1034 
     1035    /* No acccess to tsx after this, it may have been destroyed */ 
    10841036 
    10851037    return PJ_SUCCESS; 
     
    10941046    pjsip_event event; 
    10951047    pjsip_transaction *tsx = (pjsip_transaction*) entry->user_data; 
    1096     struct tsx_lock_data lck; 
    10971048 
    10981049    PJ_UNUSED_ARG(theap); 
     
    11081059 
    11091060    /* Dispatch event to transaction. */ 
    1110     lock_tsx(tsx, &lck); 
     1061    pj_grp_lock_acquire(tsx->grp_lock); 
    11111062    (*tsx->state_handler)(tsx, &event); 
    1112     unlock_tsx(tsx, &lck); 
     1063    pj_grp_lock_release(tsx->grp_lock); 
    11131064 
    11141065    pj_log_pop_indent(); 
     
    12091160 
    12101161        /* Destroy transaction. */ 
    1211         tsx_destroy(tsx); 
     1162        tsx_shutdown(tsx); 
    12121163    } 
    12131164 
     
    12211172PJ_DEF(pj_status_t) pjsip_tsx_create_uac( pjsip_module *tsx_user, 
    12221173                                          pjsip_tx_data *tdata, 
     1174                                          pjsip_transaction **p_tsx) 
     1175{ 
     1176    return pjsip_tsx_create_uac2(tsx_user, tdata, NULL, p_tsx); 
     1177} 
     1178 
     1179PJ_DEF(pj_status_t) pjsip_tsx_create_uac2(pjsip_module *tsx_user, 
     1180                                          pjsip_tx_data *tdata, 
     1181                                          pj_grp_lock_t *grp_lock, 
    12231182                                          pjsip_transaction **p_tsx) 
    12241183{ 
     
    12281187    pjsip_via_hdr *via; 
    12291188    pjsip_host_info dst_info; 
    1230     struct tsx_lock_data lck; 
    12311189    pj_status_t status; 
    12321190 
     
    12521210 
    12531211    /* Create transaction instance. */ 
    1254     status = tsx_create( tsx_user, &tsx); 
     1212    status = tsx_create( tsx_user, grp_lock, &tsx); 
    12551213    if (status != PJ_SUCCESS) 
    12561214        return status; 
     
    12581216 
    12591217    /* Lock transaction. */ 
    1260     lock_tsx(tsx, &lck); 
     1218    pj_grp_lock_acquire(tsx->grp_lock); 
    12611219 
    12621220    /* Role is UAC. */ 
     
    13241282    status = pjsip_get_request_dest(tdata, &dst_info); 
    13251283    if (status != PJ_SUCCESS) { 
    1326         unlock_tsx(tsx, &lck); 
    1327         tsx_destroy(tsx); 
     1284        pj_grp_lock_release(tsx->grp_lock); 
     1285        tsx_shutdown(tsx); 
    13281286        return status; 
    13291287    } 
     
    13361294        pj_assert(!"Bug in branch_param generator (i.e. not unique)"); 
    13371295        */ 
    1338         unlock_tsx(tsx, &lck); 
    1339         tsx_destroy(tsx); 
     1296        pj_grp_lock_release(tsx->grp_lock); 
     1297        tsx_shutdown(tsx); 
    13401298        return status; 
    13411299    } 
     
    13431301 
    13441302    /* Unlock transaction and return. */ 
    1345     unlock_tsx(tsx, &lck); 
     1303    pj_grp_lock_release(tsx->grp_lock); 
    13461304 
    13471305    pj_log_push_indent(); 
     
    13601318PJ_DEF(pj_status_t) pjsip_tsx_create_uas( pjsip_module *tsx_user, 
    13611319                                          pjsip_rx_data *rdata, 
     1320                                          pjsip_transaction **p_tsx) 
     1321{ 
     1322    return pjsip_tsx_create_uas2(tsx_user, rdata, NULL, p_tsx); 
     1323} 
     1324 
     1325PJ_DEF(pj_status_t) pjsip_tsx_create_uas2(pjsip_module *tsx_user, 
     1326                                          pjsip_rx_data *rdata, 
     1327                                          pj_grp_lock_t *grp_lock, 
    13621328                                          pjsip_transaction **p_tsx) 
    13631329{ 
     
    13671333    pjsip_cseq_hdr *cseq; 
    13681334    pj_status_t status; 
    1369     struct tsx_lock_data lck; 
    13701335 
    13711336    /* Validate arguments. */ 
     
    14051370     * Create transaction instance.  
    14061371     */ 
    1407     status = tsx_create( tsx_user, &tsx); 
     1372    status = tsx_create( tsx_user, grp_lock, &tsx); 
    14081373    if (status != PJ_SUCCESS) 
    14091374        return status; 
     
    14111376 
    14121377    /* Lock transaction. */ 
    1413     lock_tsx(tsx, &lck); 
     1378    pj_grp_lock_acquire(tsx->grp_lock); 
    14141379 
    14151380    /* Role is UAS */ 
     
    14281393                                  PJSIP_ROLE_UAS, &tsx->method, rdata); 
    14291394    if (status != PJ_SUCCESS) { 
    1430         unlock_tsx(tsx, &lck); 
    1431         tsx_destroy(tsx); 
     1395        pj_grp_lock_release(tsx->grp_lock); 
     1396        tsx_shutdown(tsx); 
    14321397        return status; 
    14331398    } 
     
    14551420    status = pjsip_get_response_addr( tsx->pool, rdata, &tsx->res_addr ); 
    14561421    if (status != PJ_SUCCESS) { 
    1457         unlock_tsx(tsx, &lck); 
    1458         tsx_destroy(tsx); 
     1422        pj_grp_lock_release(tsx->grp_lock); 
     1423        tsx_shutdown(tsx); 
    14591424        return status; 
    14601425    } 
     
    14771442    status = mod_tsx_layer_register_tsx(tsx); 
    14781443    if (status != PJ_SUCCESS) { 
    1479         unlock_tsx(tsx, &lck); 
    1480         tsx_destroy(tsx); 
     1444        pj_grp_lock_release(tsx->grp_lock); 
     1445        tsx_shutdown(tsx); 
    14811446        return status; 
    14821447    } 
     
    14861451 
    14871452    /* Unlock transaction and return. */ 
    1488     unlock_tsx(tsx, &lck); 
     1453    pj_grp_lock_release(tsx->grp_lock); 
    14891454 
    14901455    pj_log_push_indent(); 
     
    15051470                                            const pjsip_tpselector *sel) 
    15061471{ 
    1507     struct tsx_lock_data lck; 
    1508  
    15091472    /* Must be UAC transaction */ 
    15101473    PJ_ASSERT_RETURN(tsx && sel, PJ_EINVAL); 
    15111474 
    15121475    /* Start locking the transaction. */ 
    1513     lock_tsx(tsx, &lck); 
     1476    pj_grp_lock_acquire(tsx->grp_lock); 
    15141477 
    15151478    /* Decrement reference counter of previous transport selector */ 
     
    15231486 
    15241487    /* Unlock transaction. */ 
    1525     unlock_tsx(tsx, &lck); 
     1488    pj_grp_lock_release(tsx->grp_lock); 
    15261489 
    15271490    return PJ_SUCCESS; 
     
    15481511PJ_DEF(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx, int code ) 
    15491512{ 
    1550     struct tsx_lock_data lck; 
    1551  
    15521513    PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL); 
    15531514 
     
    15611522    pj_log_push_indent(); 
    15621523 
    1563     lock_tsx(tsx, &lck); 
     1524    pj_grp_lock_acquire(tsx->grp_lock); 
    15641525    tsx_set_status_code(tsx, code, NULL); 
    15651526    tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, PJSIP_EVENT_USER, NULL); 
    1566     unlock_tsx(tsx, &lck); 
     1527    pj_grp_lock_release(tsx->grp_lock); 
    15671528 
    15681529    pj_log_pop_indent(); 
     
    15791540PJ_DEF(pj_status_t) pjsip_tsx_stop_retransmit(pjsip_transaction *tsx) 
    15801541{ 
    1581     struct tsx_lock_data lck; 
    1582  
    15831542    PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL); 
    15841543    PJ_ASSERT_RETURN(tsx->role == PJSIP_ROLE_UAC && 
     
    15901549    pj_log_push_indent(); 
    15911550 
    1592     lock_tsx(tsx, &lck); 
     1551    pj_grp_lock_acquire(tsx->grp_lock); 
    15931552    /* Cancel retransmission timer. */ 
    15941553    if (tsx->retransmit_timer.id != 0) { 
     
    15961555        tsx->retransmit_timer.id = 0; 
    15971556    } 
    1598     unlock_tsx(tsx, &lck); 
     1557    pj_grp_lock_release(tsx->grp_lock); 
    15991558 
    16001559    pj_log_pop_indent(); 
     
    16181577                     PJ_EINVALIDOP); 
    16191578 
    1620     /* Note: must not call lock_tsx() as that would introduce deadlock. 
    1621      * See #1121. 
     1579    /* Note: must not call pj_grp_lock_acquire(tsx->grp_lock) as 
     1580     * that would introduce deadlock. See #1121. 
    16221581     */ 
    16231582    lock_timer(tsx); 
     
    16601619{ 
    16611620    pjsip_event event; 
    1662     struct tsx_lock_data lck; 
    16631621    pj_status_t status; 
    16641622 
     
    16761634 
    16771635    /* Dispatch to transaction. */ 
    1678     lock_tsx(tsx, &lck); 
     1636    pj_grp_lock_acquire(tsx->grp_lock); 
    16791637 
    16801638    /* Set transport selector to tdata */ 
     
    16841642    status = (*tsx->state_handler)(tsx, &event); 
    16851643 
    1686     unlock_tsx(tsx, &lck); 
     1644    pj_grp_lock_release(tsx->grp_lock); 
    16871645 
    16881646    /* Only decrement reference counter when it returns success. 
     
    17071665{ 
    17081666    pjsip_event event; 
    1709     struct tsx_lock_data lck; 
    1710     pj_status_t status; 
    17111667 
    17121668    PJ_LOG(5,(tsx->obj_name, "Incoming %s in state %s",  
     
    17211677 
    17221678    /* Dispatch to transaction. */ 
    1723     lock_tsx(tsx, &lck); 
    1724     status = (*tsx->state_handler)(tsx, &event); 
    1725     unlock_tsx(tsx, &lck); 
     1679    pj_grp_lock_acquire(tsx->grp_lock); 
     1680    (*tsx->state_handler)(tsx, &event); 
     1681    pj_grp_lock_release(tsx->grp_lock); 
    17261682 
    17271683    pj_log_pop_indent(); 
     
    17351691    pjsip_transaction *tsx = (pjsip_transaction*) send_state->token; 
    17361692    pjsip_tx_data *tdata = send_state->tdata; 
    1737     struct tsx_lock_data lck; 
    17381693 
    17391694    /* Check if transaction has cancelled itself from this transmit 
     
    17491704    } 
    17501705 
     1706    pj_grp_lock_acquire(tsx->grp_lock); 
     1707 
    17511708    /* Reset */ 
    17521709    tdata->mod_data[mod_tsx_layer.mod.id] = NULL; 
    17531710    tsx->pending_tx = NULL; 
    1754  
    1755     lock_tsx(tsx, &lck); 
    17561711 
    17571712    if (sent > 0) { 
     
    17831738            tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED,  
    17841739                           PJSIP_EVENT_UNKNOWN, NULL ); 
    1785             unlock_tsx(tsx, &lck); 
     1740            pj_grp_lock_release(tsx->grp_lock); 
    17861741            return; 
    17871742        } 
     
    18251780            err =pj_strerror(-sent, errmsg, sizeof(errmsg)); 
    18261781 
    1827             PJ_LOG(2,(tsx->obj_name,  
     1782            PJ_LOG(2,(tsx->obj_name, 
    18281783                      "Failed to send %s! err=%d (%s)", 
    18291784                      pjsip_tx_data_get_info(send_state->tdata), -sent, 
     
    18631818 
    18641819        } else { 
    1865             char errmsg[PJ_ERR_MSG_SIZE]; 
    1866  
    1867             PJ_LOG(2,(tsx->obj_name,  
    1868                       "Temporary failure in sending %s, " 
    1869                       "will try next server. Err=%d (%s)", 
    1870                       pjsip_tx_data_get_info(send_state->tdata), -sent, 
    1871                       pj_strerror(-sent, errmsg, sizeof(errmsg)).ptr)); 
     1820            PJ_PERROR(2,(tsx->obj_name, -sent, 
     1821                         "Temporary failure in sending %s, " 
     1822                         "will try next server", 
     1823                         pjsip_tx_data_get_info(send_state->tdata))); 
    18721824 
    18731825            /* Reset retransmission count */ 
     
    18941846    } 
    18951847 
    1896     unlock_tsx(tsx, &lck); 
     1848    pj_grp_lock_release(tsx->grp_lock); 
    18971849} 
    18981850 
     
    19041856    if (sent < 0) { 
    19051857        pjsip_transaction *tsx = (pjsip_transaction*) token; 
    1906         struct tsx_lock_data lck; 
    19071858        char errmsg[PJ_ERR_MSG_SIZE]; 
    19081859        pj_str_t err; 
     
    19131864 
    19141865        PJ_LOG(2,(tsx->obj_name, "Transport failed to send %s! Err=%d (%s)", 
    1915                   pjsip_tx_data_get_info(tdata), -sent, errmsg)); 
    1916  
    1917         lock_tsx(tsx, &lck); 
     1866                pjsip_tx_data_get_info(tdata), -sent, errmsg)); 
     1867 
     1868        pj_grp_lock_acquire(tsx->grp_lock); 
    19181869 
    19191870        /* Release transport. */ 
     
    19251876                       PJSIP_EVENT_TRANSPORT_ERROR, tdata ); 
    19261877 
    1927         unlock_tsx(tsx, &lck); 
     1878        pj_grp_lock_release(tsx->grp_lock); 
    19281879   } 
    19291880} 
     
    19411892    if (state == PJSIP_TP_STATE_DISCONNECTED) { 
    19421893        pjsip_transaction *tsx; 
    1943         struct tsx_lock_data lck; 
    19441894 
    19451895        pj_assert(tp && info && info->user_data); 
     
    19471897        tsx = (pjsip_transaction*)info->user_data; 
    19481898 
    1949         lock_tsx(tsx, &lck); 
     1899        pj_grp_lock_acquire(tsx->grp_lock); 
    19501900 
    19511901        /* Terminate transaction when transport disconnected */ 
     
    19601910        } 
    19611911 
    1962         unlock_tsx(tsx, &lck); 
     1912        pj_grp_lock_release(tsx->grp_lock); 
    19631913    } 
    19641914} 
     
    19921942 
    19931943        if (status != PJ_SUCCESS) { 
    1994             char errmsg[PJ_ERR_MSG_SIZE]; 
    1995  
    1996             PJ_LOG(2,(tsx->obj_name,  
    1997                       "Error sending %s: Err=%d (%s)", 
    1998                       pjsip_tx_data_get_info(tdata), status,  
    1999                       pj_strerror(status, errmsg, sizeof(errmsg)).ptr)); 
     1944            PJ_PERROR(2,(tsx->obj_name, status, 
     1945                         "Error sending %s", 
     1946                         pjsip_tx_data_get_info(tdata))); 
    20001947 
    20011948            /* On error, release transport to force using full transport 
     
    21102057                                                  pjsip_tx_data *tdata) 
    21112058{ 
    2112     struct tsx_lock_data lck; 
    21132059    pj_status_t status; 
    21142060 
    2115     lock_tsx(tsx, &lck); 
     2061    pj_grp_lock_acquire(tsx->grp_lock); 
    21162062    if (tdata == NULL) { 
    21172063        tdata = tsx->last_tx; 
    21182064    } 
    21192065    status = tsx_send_msg(tsx, tdata); 
    2120     unlock_tsx(tsx, &lck); 
     2066    pj_grp_lock_release(tsx->grp_lock); 
    21212067 
    21222068    /* Only decrement reference counter when it returns success. 
Note: See TracChangeset for help on using the changeset viewer.