Changeset 3311


Ignore:
Timestamp:
Sep 15, 2010 7:42:14 AM (10 years ago)
Author:
bennylp
Message:

Fix #1121 (Deadlock in transaction code when hanging up calls (thanks Dennis Struble for the report))

Location:
pjproject/trunk/pjsip
Files:
2 edited

Legend:

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

    r3138 r3311  
    8787    pjsip_endpoint             *endpt;          /**< Endpoint instance.     */ 
    8888    pj_mutex_t                 *mutex;          /**< Mutex for this tsx.    */ 
     89    pj_mutex_t                 *mutex_b;        /**< Second mutex to avoid 
     90                                                     deadlock. It is used to 
     91                                                     protect timer.         */ 
    8992 
    9093    /* 
  • pjproject/trunk/pjsip/src/pjsip/sip_transaction.c

    r3262 r3311  
    951951 
    952952 
     953/* Lock transaction for accessing the timeout timer only. */ 
     954static void lock_timer(pjsip_transaction *tsx) 
     955{ 
     956    pj_mutex_lock(tsx->mutex_b); 
     957} 
     958 
     959/* Unlock timer */ 
     960static void unlock_timer(pjsip_transaction *tsx) 
     961{ 
     962    pj_mutex_unlock(tsx->mutex_b); 
     963} 
     964 
    953965/* Create and initialize basic transaction structure. 
    954966 * This function is called by both UAC and UAS creation. 
     
    9891001    } 
    9901002 
     1003    status = pj_mutex_create_simple(pool, tsx->obj_name, &tsx->mutex_b); 
     1004    if (status != PJ_SUCCESS) { 
     1005        pj_mutex_destroy(tsx->mutex); 
     1006        pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool); 
     1007        return status; 
     1008    } 
     1009 
    9911010    *p_tsx = tsx; 
    9921011    return PJ_SUCCESS; 
     
    10421061    } 
    10431062 
     1063    pj_mutex_destroy(tsx->mutex_b); 
    10441064    pj_mutex_destroy(tsx->mutex); 
    10451065 
     
    11501170        } 
    11511171 
     1172        lock_timer(tsx); 
     1173 
    11521174        /* Cancel timeout timer. */ 
    11531175        if (tsx->timeout_timer.id != 0) { 
     
    11601182                                    &timeout); 
    11611183 
     1184        unlock_timer(tsx); 
    11621185 
    11631186    } else if (state == PJSIP_TSX_STATE_DESTROYED) { 
     
    15581581                                           unsigned millisec) 
    15591582{ 
    1560     struct tsx_lock_data lck; 
    15611583    pj_time_val timeout; 
    15621584 
     
    15661588                     PJ_EINVALIDOP); 
    15671589 
    1568     lock_tsx(tsx, &lck); 
     1590    /* Note: must not call lock_tsx() as that would introduce deadlock. 
     1591     * See #1121. 
     1592     */ 
     1593    lock_timer(tsx); 
    15691594 
    15701595    /* Transaction must not have got final response */ 
    15711596    PJ_ASSERT_ON_FAIL(tsx->status_code < 200, 
    1572                     { unlock_tsx(tsx, &lck); return PJ_EINVALIDOP; }); 
     1597                    { unlock_timer(tsx); return PJ_EINVALIDOP; }); 
    15731598 
    15741599    if (tsx->timeout_timer.id != 0) { 
     
    15861611 
    15871612 
    1588     unlock_tsx(tsx, &lck); 
     1613    unlock_timer(tsx); 
    15891614 
    15901615    return PJ_SUCCESS; 
     
    18051830            /* And reset timeout timer */ 
    18061831            if (tsx->timeout_timer.id) { 
     1832                lock_timer(tsx); 
     1833 
    18071834                pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); 
    18081835                tsx->timeout_timer.id = TIMER_INACTIVE; 
     
    18111838                pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
    18121839                                            &timeout_timer_val); 
     1840 
     1841                unlock_timer(tsx); 
    18131842            } 
    18141843 
     
    22082237         * timeout. 
    22092238         */ 
     2239        lock_timer(tsx); 
    22102240        tsx->timeout_timer.id = TIMER_ACTIVE; 
    22112241        pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
    22122242                                    &timeout_timer_val); 
     2243        unlock_timer(tsx); 
    22132244 
    22142245        /* Start Timer A (or timer E) for retransmission only if unreliable  
     
    23002331 
    23012332            if (tsx->timeout_timer.id != 0) { 
     2333                lock_timer(tsx); 
    23022334                pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); 
    23032335                tsx->timeout_timer.id = 0; 
     2336                unlock_timer(tsx); 
    23042337            } 
    23052338 
     
    23222355 
    23232356                /* Cancel timeout timer */ 
     2357                lock_timer(tsx); 
    23242358                pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer); 
     2359                unlock_timer(tsx); 
    23252360 
    23262361            } else { 
     
    25732608                } 
    25742609 
     2610                lock_timer(tsx); 
    25752611                tsx->timeout_timer.id = TIMER_ACTIVE; 
    25762612                pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
    25772613                                            &timeout); 
     2614                unlock_timer(tsx); 
    25782615 
    25792616                /* Set state to "Completed" */ 
     
    26032640             * non-reliable transports, and zero for reliable transports. 
    26042641             */ 
     2642            lock_timer(tsx); 
    26052643            if (tsx->method.id == PJSIP_INVITE_METHOD) { 
    26062644                /* Start timer H for INVITE */ 
     
    26202658                                           &zero_time); 
    26212659            } 
     2660            unlock_timer(tsx); 
    26222661 
    26232662            /* For INVITE, if unreliable transport is used, retransmission  
     
    27472786 
    27482787        /* Stop timeout timer B/F. */ 
     2788        lock_timer(tsx); 
    27492789        pjsip_endpt_cancel_timer( tsx->endpt, &tsx->timeout_timer ); 
     2790        unlock_timer(tsx); 
    27502791 
    27512792        /* For INVITE, the state moves to Terminated state (because ACK is 
     
    27712812                timeout.sec = timeout.msec = 0; 
    27722813            } 
     2814            lock_timer(tsx); 
    27732815            tsx->timeout_timer.id = TIMER_ACTIVE; 
    27742816            pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
    27752817                                        &timeout); 
     2818            unlock_timer(tsx); 
    27762819 
    27772820            /* Cancel retransmission timer */ 
     
    28652908 
    28662909        /* Stop timer B. */ 
     2910        lock_timer(tsx); 
    28672911        tsx->timeout_timer.id = 0; 
    28682912        pjsip_endpt_cancel_timer( tsx->endpt, &tsx->timeout_timer ); 
     2913        unlock_timer(tsx); 
    28692914 
    28702915        /* Generate and send ACK (for INVITE) */ 
     
    29132958            timeout.sec = timeout.msec = 0; 
    29142959        } 
     2960        lock_timer(tsx); 
    29152961        tsx->timeout_timer.id = TIMER_ACTIVE; 
    29162962        pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout); 
     2963        unlock_timer(tsx); 
    29172964 
    29182965    } else { 
     
    29723019 
    29733020            /* Reschedule timeout timer. */ 
     3021            lock_timer(tsx); 
    29743022            pjsip_endpt_cancel_timer( tsx->endpt, &tsx->timeout_timer ); 
    29753023            tsx->timeout_timer.id = TIMER_ACTIVE; 
     
    29873035            pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,  
    29883036                                        &timeout); 
     3037            unlock_timer(tsx); 
    29893038 
    29903039            /* Move state to "Confirmed" */ 
Note: See TracChangeset for help on using the changeset viewer.