--- svn_chan_sip.c 2008-10-23 20:26:50.968750000 +0200 +++ patched_chan_sip.c 2008-10-25 01:44:24.218750000 +0200 @@ -1686,6 +1686,9 @@ SDP_T38_ACCEPT, /*!< Remote side accepted our T38 request */ }; +/*! \brief Protect the callcounters counter */ +AST_MUTEX_DEFINE_STATIC(callctrlock); + /*---------------------------- Forward declarations of functions in chan_sip.c */ /* Note: This is added to help splitting up chan_sip.c into several files in coming releases. */ @@ -4481,6 +4484,8 @@ int outgoing = fup->outgoing_call; struct sip_user *u = NULL; struct sip_peer *p = NULL; + int ctrproblem=FALSE; + int ctrdebug=0; ast_debug(3, "Updating call counter for %s call\n", outgoing ? "outgoing" : "incoming"); @@ -4512,20 +4517,50 @@ /* incoming and outgoing affects the inUse counter */ case DEC_CALL_LIMIT: /* Decrement inuse count if applicable */ - if (inuse && ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) { - ast_atomic_fetchadd_int(inuse, -1); - ast_clear_flag(&fup->flags[0], SIP_INC_COUNT); - } else - *inuse = 0; + ctrproblem=FALSE; + if (inuse) { + ast_mutex_lock(&callctrlock); + if((*inuse > 0) && ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) { + (*inuse)--; + ast_clear_flag(&fup->flags[0], SIP_INC_COUNT); + } else if (*inuse < 0) { + ctrproblem=TRUE; + ctrdebug=*inuse; + *inuse = 0; + } + ast_mutex_unlock(&callctrlock); + } + if(ctrproblem) { + ast_debug(2, "Bug13668: inuse %i corrected to 0 @1\n", ctrdebug); + ctrproblem=FALSE; + } + /* Decrement ringing count if applicable */ - if (inringing && ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { - ast_atomic_fetchadd_int(inringing, -1); - ast_clear_flag(&fup->flags[0], SIP_INC_RINGING); + if (inringing) { + ast_mutex_lock(&callctrlock); + if((*inringing > 0)&& ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { + (*inringing)--; + ast_clear_flag(&fup->flags[0], SIP_INC_RINGING); + } else if (*inringing < 0) { + ctrproblem=TRUE; + ctrdebug=*inringing; + *inringing = 0; + } + ast_mutex_unlock(&callctrlock); + } + if(ctrproblem) { + ast_debug(2, "Bug13668: inringing %i corrected to 0 @2\n", ctrdebug); + ctrproblem=FALSE; } + /* Decrement onhold count if applicable */ + ast_mutex_lock(&callctrlock); if (ast_test_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD) && global_notifyhold) { ast_clear_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD); + ast_mutex_unlock(&callctrlock); sip_peer_hold(fup, FALSE); + } else { + ast_mutex_unlock(&callctrlock); } if (sipdebug) ast_debug(2, "Call %s %s '%s' removed from call limit %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *call_limit); @@ -4544,30 +4579,101 @@ return -1; } } + ctrproblem=FALSE; if (inringing && (event == INC_CALL_RINGING)) { - if (!ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { - ast_atomic_fetchadd_int(inringing, +1); + ast_mutex_lock(&callctrlock); + if ((*inringing >= 0)&& !ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { + (*inringing)++; ast_set_flag(&fup->flags[0], SIP_INC_RINGING); + } else if (*inringing < 0) { + ctrproblem=TRUE; + ctrdebug=*inringing; + *inringing = 1; + } + ast_mutex_unlock(&callctrlock); + if(ctrproblem) { + ast_debug(2, "Bug13668: inringing %i corrected to 1 @3\n", ctrdebug); + ctrproblem=FALSE; } } /* Continue */ - ast_atomic_fetchadd_int(inuse, +1); - ast_set_flag(&fup->flags[0], SIP_INC_COUNT); + if(inuse) { + ast_mutex_lock(&callctrlock); + if((*inuse >= 0) && !ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) { + (*inuse)++; + ast_set_flag(&fup->flags[0], SIP_INC_COUNT); + } else { + ctrproblem=TRUE; + ctrdebug=*inuse; + *inuse = 1; + } + ast_mutex_unlock(&callctrlock); + } + if(ctrproblem) { + ast_debug(2, "Bug13668: inuse %i corrected to 1 @4\n", ctrdebug); + ctrproblem=FALSE; + } if (sipdebug) { ast_debug(2, "Call %s %s '%s' is %d out of %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *inuse, *call_limit); } break; case DEC_CALL_RINGING: - if (inringing && ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { - ast_atomic_fetchadd_int(inringing, -1); - ast_clear_flag(&fup->flags[0], SIP_INC_RINGING); + ctrproblem=FALSE; + if (inringing ) { + ast_mutex_lock(&callctrlock); + if((*inringing > 0) && ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { + (*inringing)--; + ast_clear_flag(&fup->flags[0], SIP_INC_RINGING); + } else if (*inringing < 0) { + ctrproblem=TRUE; + ctrdebug=*inringing; + *inringing = 0; + } + ast_mutex_unlock(&callctrlock); + } + if(ctrproblem) { + ast_debug(2, "Bug13668: inringing %i corrected to 0 @5\n", ctrdebug); + ctrproblem=FALSE; } break; default: ast_log(LOG_ERROR, "update_call_counter(%s, %d) called with no event!\n", name, event); } + /* *******************************************/ + /* remember murphy! */ + /* to be removed tests are successful */ + ctrproblem=FALSE; + if (inringing ) { + ast_mutex_lock(&callctrlock); + if (*inringing < 0) { + ctrproblem=TRUE; + ctrdebug=*inringing; + *inringing = 0; + } + ast_mutex_unlock(&callctrlock); + } + if(ctrproblem) { + ast_debug(2, "Bug13668: inringing %i corrected to 0 @6\n", ctrdebug); + ctrproblem=FALSE; + } + if (inuse) { + ast_mutex_lock(&callctrlock); + if (*inuse < 0) { + ctrproblem=TRUE; + ctrdebug=*inuse; + *inuse = 0; + } + ast_mutex_unlock(&callctrlock); + } + if(ctrproblem) { + ast_debug(2, "Bug13668: inuse %i corrected to 0 @7\n", ctrdebug); + ctrproblem=FALSE; + } + /* ********************************************/ + + if (p) { ast_device_state_changed("SIP/%s", p->name); unref_peer(p);