Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 30626) +++ channels/chan_sip.c (working copy) @@ -1181,7 +1181,8 @@ pkt->timer_a = 2 * pkt->timer_a; /* For non-invites, a maximum of 4 secs */ - siptimer_a = pkt->timer_t1 * pkt->timer_a; /* Double each time */ + //siptimer_a = pkt->timer_t1 * pkt->timer_a; /* Double each time */ + siptimer_a = DEFAULT_RETRANS * pkt->timer_a; if (pkt->method != SIP_INVITE && siptimer_a > 4000) siptimer_a = 4000; @@ -1214,7 +1215,7 @@ } append_history(pkt->owner, "MaxRetries", (ast_test_flag(pkt, FLAG_FATAL)) ? "(Critical)" : "(Non-critical)"); - pkt->retransid = -1; + //pkt->retransid = -1; if (ast_test_flag(pkt, FLAG_FATAL)) { while(pkt->owner->owner && ast_mutex_trylock(&pkt->owner->owner->lock)) { @@ -1251,7 +1252,7 @@ pkt = NULL; } else ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n"); - if (pkt) + if (pkt && pkt->owner) ast_mutex_unlock(&pkt->owner->lock); return 0; } @@ -1277,8 +1278,8 @@ pkt->timer_t1 = p->timer_t1; /* Set SIP timer T1 */ if (fatal) ast_set_flag(pkt, FLAG_FATAL); - if (pkt->timer_t1) - siptimer_a = pkt->timer_t1 * 2; + if (pkt->timer_a) + siptimer_a = pkt->timer_a * siptimer_a; /* Schedule retransmission */ pkt->retransid = ast_sched_add_variable(sched, siptimer_a, retrans_pkt, pkt, 1); @@ -1381,8 +1382,9 @@ if (cur->retransid > -1) { if (sipdebug && option_debug > 3) ast_log(LOG_DEBUG, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid); - ast_sched_del(sched, cur->retransid); + ast_sched_del_with_lock(sched, cur->retransid); } + cur->retransid = -1; free(cur); res = 0; break; @@ -2172,13 +2174,18 @@ if (p->initid > -1) ast_sched_del(sched, p->initid); + ast_mutex_lock(&p->lock); while((cp = p->packets)) { p->packets = p->packets->next; if (cp->retransid > -1) { - ast_sched_del(sched, cp->retransid); - } + ast_sched_del_with_lock(sched, cp->retransid); + } + cp->retransid = -1; free(cp); } + + ast_mutex_unlock(&p->lock); + if (p->chanvars) { ast_variables_destroy(p->chanvars); p->chanvars = NULL; Index: sched.c =================================================================== --- sched.c (revision 30626) +++ sched.c (working copy) @@ -60,6 +60,7 @@ struct sched_context { ast_mutex_t lock; + ast_mutex_t del_lock; /* Number of events processed */ int eventcnt; @@ -83,6 +84,7 @@ if (tmp) { memset(tmp, 0, sizeof(struct sched_context)); ast_mutex_init(&tmp->lock); + ast_mutex_init(&tmp->del_lock); tmp->eventcnt = 1; tmp->schedcnt = 0; tmp->schedq = NULL; @@ -302,6 +304,17 @@ return 0; } +int ast_sched_del_with_lock(struct sched_context *con, int id) +{ + int res; + + ast_mutex_lock(&con->del_lock); + res = ast_sched_del(con, id); + ast_mutex_unlock(&con->del_lock); + + return res; + } + void ast_sched_dump(const struct sched_context *con) { /* @@ -343,7 +356,9 @@ int x=0; int res; DEBUG(ast_log(LOG_DEBUG, "ast_sched_runq()\n")); - + + ast_mutex_lock(&con->del_lock); + ast_mutex_lock(&con->lock); for(;;) { if (!con->schedq) @@ -391,6 +406,9 @@ break; } ast_mutex_unlock(&con->lock); + + ast_mutex_unlock(&con->del_lock); + return x; } Index: include/asterisk/sched.h =================================================================== --- include/asterisk/sched.h (revision 30626) +++ include/asterisk/sched.h (working copy) @@ -102,6 +102,16 @@ */ extern int ast_sched_del(struct sched_context *con, int id); +/*! Deletes a scheduled event with sched_del lock */ +/*! +* \param con scheduling context to delete item from +* \param id ID of the scheduled item to delete +* Remove this event from being run. A procedure should not remove its +* own event, but return 0 instead. +* Returns 0 on success, -1 on failure +*/ +extern int ast_sched_del_with_lock(struct sched_context *con, int id); + /*! Determines number of seconds until the next outstanding event to take place */ /*! * \param con context to act upon