Index: t_cancel.c =================================================================== RCS file: /cvsroot/ser/sip_router/modules/tm/t_cancel.c,v retrieving revision 1.13.2.1 diff -u -r1.13.2.1 t_cancel.c --- t_cancel.c 13 Jun 2006 13:31:48 -0000 1.13.2.1 +++ t_cancel.c 28 Nov 2006 00:27:42 -0000 @@ -147,7 +147,7 @@ /* stop_rb_timers(&t->uac[i].request); */ reset_timer( &t->uac[i].request.retr_timer ); - reset_timer( &t->uac[i].request.fr_timer ); + del_fr_timer( &t->uac[i].request.fr_timer ); } else { Index: t_funcs.c =================================================================== RCS file: /cvsroot/ser/sip_router/modules/tm/t_funcs.c,v retrieving revision 1.175.2.3 diff -u -r1.175.2.3 t_funcs.c --- t_funcs.c 28 Aug 2006 11:21:02 -0000 1.175.2.3 +++ t_funcs.c 28 Nov 2006 00:27:42 -0000 @@ -133,7 +133,7 @@ { set_kr(REQ_RLSD); - reset_timer( & trans->uas.response.fr_timer ); + del_fr_timer( & trans->uas.response.fr_timer ); reset_timer( & trans->uas.response.retr_timer ); cleanup_uac_timers( trans ); Index: t_fwd.c =================================================================== RCS file: /cvsroot/ser/sip_router/modules/tm/t_fwd.c,v retrieving revision 1.61.2.2 diff -u -r1.61.2.2 t_fwd.c --- t_fwd.c 28 Aug 2006 11:21:02 -0000 1.61.2.2 +++ t_fwd.c 28 Nov 2006 00:27:42 -0000 @@ -349,7 +349,7 @@ * retransmission timers */ reset_timer(&t_invite->uac[i].request.retr_timer); - reset_timer(&t_invite->uac[i].request.fr_timer); + del_fr_timer(&t_invite->uac[i].request.fr_timer); /* Generate faked reply */ LOCK_REPLIES(t_invite); Index: t_reply.c =================================================================== RCS file: /cvsroot/ser/sip_router/modules/tm/t_reply.c,v retrieving revision 1.98.2.6 diff -u -r1.98.2.6 t_reply.c --- t_reply.c 12 Jun 2006 08:22:48 -0000 1.98.2.6 +++ t_reply.c 28 Nov 2006 00:27:43 -0000 @@ -66,6 +66,7 @@ * the request (bogdan) * 2005-09-01 reverted to the old way of checking response.dst.send_sock * in t_retransmit_reply & reply_light (andrei) + * 2006-12-27 replaced reset(fr_timer) with del_fr_timer(...) (andrei) */ @@ -954,7 +955,7 @@ /* reset FR/retransmission timers */ for (i=0; inr_of_outgoings; i++ ) { reset_timer( &t->uac[i].request.retr_timer ); - reset_timer( &t->uac[i].request.fr_timer ); + del_fr_timer( &t->uac[i].request.fr_timer ); } DBG("DEBUG: cleanup_uac_timers: RETR/FR timers reset\n"); } @@ -1282,7 +1283,7 @@ /* ... then just stop timers */ reset_timer( &uac->local_cancel.retr_timer); if ( msg_status >= 200 ) { - reset_timer( &uac->local_cancel.fr_timer); + del_fr_timer( &uac->local_cancel.fr_timer); } DBG("DEBUG: reply to local CANCEL processed\n"); goto done; @@ -1294,7 +1295,7 @@ /* stop final response timer only if I got a final response */ if ( msg_status >= 200 ) { - reset_timer( &uac->request.fr_timer); + del_fr_timer(&uac->request.fr_timer); } /* acknowledge negative INVITE replies (do it before detailed Index: timer.c =================================================================== RCS file: /cvsroot/ser/sip_router/modules/tm/timer.c,v retrieving revision 1.58.2.3 diff -u -r1.58.2.3 timer.c --- timer.c 6 Dec 2005 13:20:14 -0000 1.58.2.3 +++ timer.c 28 Nov 2006 00:27:43 -0000 @@ -98,6 +98,8 @@ * 2003-06-27 timers are not unlinked if timerlist is 0 (andrei) * 2004-02-13 t->is_invite, t->local, t->noisy_ctimer replaced; * timer_link.payload removed (bogdan) + * 2006-11-27 added del_fr_timer(): fr timers are immediately removed + * from the FR* lists (andrei) */ #include "defs.h" @@ -322,7 +324,7 @@ "request resending (t=%p, %.9s ... )\n", r_buf->my_T, r_buf->buffer); if (SEND_BUFFER( r_buf )==-1) { - reset_timer( &r_buf->fr_timer ); + del_fr_timer( &r_buf->fr_timer ); fake_reply(r_buf->my_T, r_buf->branch, 503 ); return; } @@ -436,7 +438,7 @@ int i; for (i=0; inr_of_outgoings; i++ ) { reset_timer( &t->uac[i].local_cancel.retr_timer ); - reset_timer( &t->uac[i].local_cancel.fr_timer ); + del_fr_timer( &t->uac[i].local_cancel.fr_timer ); } } @@ -776,6 +778,33 @@ #endif } + + +/* remove a timer from the FR_TIMER_LIST or FR_INV_TIMER_LIST + * (it allows immediate delete of a fr timer => solves the race with + * variables timers inserted after longer deleted timers) + * WARNING: - don't try to use it to "move" a timer from one list + * to another, you'll run into races + */ +void del_fr_timer( struct timer_link *tl) +{ + /* the FR lock is common/shared by both FR_INV_TIMER_LIST + * and FR_TIMER_LIST, so we must lock only one of them */ + lock(timertable->timers[FR_TIMER_LIST].mutex); + /* check first if we are on the "detached" timer_routine list (the fr + * handle is executing or timer_routine prepares to execute it). + * if so do nothing, except reseting the timer to TIMER_DELETED + * (just to give us a change at racing with timer_routine, if + * TIMER_DELETED is set and the fr handle is not already executing => + * it will not be called anymore) + */ + if (tl->timer_list!=DETACHED_LIST){ + remove_timer_unsafe(tl); /* safe to call for null list */ + }else{ + reset_timer(tl); + } + unlock(timertable->timers[FR_TIMER_LIST].mutex); +} Index: timer.h =================================================================== RCS file: /cvsroot/ser/sip_router/modules/tm/timer.h,v retrieving revision 1.37 diff -u -r1.37 timer.h --- timer.h 1 Nov 2004 14:09:09 -0000 1.37 +++ timer.h 28 Nov 2006 00:27:43 -0000 @@ -109,6 +109,8 @@ */ void reset_timer( struct timer_link* tl ); +/* remove a timer from FR_TIMER_LIST or FR_INV_TIMER_LIST */ +void del_fr_timer( struct timer_link *tl); /* determine timer length and put on a correct timer list */ void set_timer( struct timer_link *new_tl, enum lists list_id, unsigned int* ext_timeout ); /* similar to set_timer, except it allows only one-time