Browse code

- fix for free_rdata_list() which used to access the "next" pointer after freeing the current elements (ported from Ottendorf) Credits & patch: Jan Andres <jan.andres@freenet-ag.de>

Andrei Pelinescu-Onciul authored on 29/11/2006 14:39:05
Showing 7 changed files
... ...
@@ -147,7 +147,7 @@ static void cancel_all_branches(struct cell *t)
147 147
 	    
148 148
 	    /* stop_rb_timers(&t->uac[i].request); */
149 149
 	    reset_timer( &t->uac[i].request.retr_timer );
150
-	    reset_timer( &t->uac[i].request.fr_timer );
150
+	    del_fr_timer( &t->uac[i].request.fr_timer );
151 151
 	}
152 152
 	else {
153 153
 
... ...
@@ -133,7 +133,7 @@ int t_release_transaction( struct cell *trans )
133 133
 {
134 134
 	set_kr(REQ_RLSD);
135 135
 
136
-	reset_timer( & trans->uas.response.fr_timer );
136
+	del_fr_timer( & trans->uas.response.fr_timer );
137 137
 	reset_timer( & trans->uas.response.retr_timer );
138 138
 
139 139
 	cleanup_uac_timers( trans );
... ...
@@ -349,7 +349,7 @@ void e2e_cancel( struct sip_msg *cancel_msg,
349 349
 				      * retransmission timers
350 350
 				      */
351 351
 				reset_timer(&t_invite->uac[i].request.retr_timer);
352
-				reset_timer(&t_invite->uac[i].request.fr_timer);
352
+				del_fr_timer(&t_invite->uac[i].request.fr_timer);
353 353
 
354 354
 				/* Generate faked reply */
355 355
 				LOCK_REPLIES(t_invite);
... ...
@@ -66,6 +66,7 @@
66 66
  *              the request (bogdan)
67 67
  *  2005-09-01  reverted to the old way of checking response.dst.send_sock
68 68
  *               in t_retransmit_reply & reply_light (andrei)
69
+ *  2006-12-27  replaced reset(fr_timer) with del_fr_timer(...)  (andrei)
69 70
  */
70 71
 
71 72
 
... ...
@@ -954,7 +955,7 @@ void cleanup_uac_timers( struct cell *t )
954 955
 	/* reset FR/retransmission timers */
955 956
 	for (i=0; i<t->nr_of_outgoings; i++ )  {
956 957
 		reset_timer( &t->uac[i].request.retr_timer );
957
-		reset_timer( &t->uac[i].request.fr_timer );
958
+		del_fr_timer( &t->uac[i].request.fr_timer );
958 959
 	}
959 960
 	DBG("DEBUG: cleanup_uac_timers: RETR/FR timers reset\n");
960 961
 }
... ...
@@ -1282,7 +1283,7 @@ int reply_received( struct sip_msg  *p_msg )
1282 1283
 		     /* ... then just stop timers */
1283 1284
 		reset_timer( &uac->local_cancel.retr_timer);
1284 1285
 		if ( msg_status >= 200 ) {
1285
-				reset_timer( &uac->local_cancel.fr_timer);
1286
+				del_fr_timer( &uac->local_cancel.fr_timer);
1286 1287
 		}
1287 1288
 		DBG("DEBUG: reply to local CANCEL processed\n");
1288 1289
 		goto done;
... ...
@@ -1294,7 +1295,7 @@ int reply_received( struct sip_msg  *p_msg )
1294 1295
 	
1295 1296
 	     /* stop final response timer only if I got a final response */
1296 1297
 	if ( msg_status >= 200 ) {
1297
-		reset_timer( &uac->request.fr_timer);
1298
+		del_fr_timer(&uac->request.fr_timer);
1298 1299
 	}
1299 1300
 
1300 1301
 	     /* acknowledge negative INVITE replies (do it before detailed
... ...
@@ -98,6 +98,8 @@
98 98
  *  2003-06-27  timers are not unlinked if timerlist is 0 (andrei)
99 99
  *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced;
100 100
  *              timer_link.payload removed (bogdan)
101
+ *  2006-11-27  added del_fr_timer(): fr timers are immediately removed
102
+ *              from the FR* lists (andrei)
101 103
  */
102 104
 
103 105
 #include "defs.h"
... ...
@@ -322,7 +324,7 @@ inline static void retransmission_handler( struct timer_link *retr_tl )
322 324
 				"request resending (t=%p, %.9s ... )\n", 
323 325
 				r_buf->my_T, r_buf->buffer);
324 326
 			if (SEND_BUFFER( r_buf )==-1) {
325
-				reset_timer( &r_buf->fr_timer );
327
+				del_fr_timer( &r_buf->fr_timer );
326 328
 				fake_reply(r_buf->my_T, r_buf->branch, 503 );
327 329
 				return;
328 330
 			}
... ...
@@ -436,7 +438,7 @@ void cleanup_localcancel_timers( struct cell *t )
436 438
 	int i;
437 439
 	for (i=0; i<t->nr_of_outgoings; i++ )  {
438 440
 		reset_timer(  &t->uac[i].local_cancel.retr_timer );
439
-		reset_timer(  &t->uac[i].local_cancel.fr_timer );
441
+		del_fr_timer(  &t->uac[i].local_cancel.fr_timer );
440 442
 	}
441 443
 }
442 444
 
... ...
@@ -778,6 +780,33 @@ void reset_timer( struct timer_link* tl )
778 780
 
779 781
 
780 782
 
783
+/* remove a timer from the FR_TIMER_LIST or FR_INV_TIMER_LIST
784
+ *  (it allows immediate delete of a fr timer => solves the race with
785
+ *   variables timers inserted after longer deleted timers)
786
+ * WARNING: - don't try to use it to "move" a timer from one list
787
+ *            to another, you'll run into races
788
+ */
789
+void del_fr_timer( struct timer_link *tl)
790
+{
791
+	/* the FR lock is common/shared by both FR_INV_TIMER_LIST 
792
+	 * and FR_TIMER_LIST, so we must lock only one of them */
793
+	lock(timertable->timers[FR_TIMER_LIST].mutex);
794
+	/* check first if we  are on  the "detached" timer_routine list (the fr
795
+	 * handle is executing or  timer_routine prepares to execute it).
796
+	 * if so do nothing, except reseting the timer to TIMER_DELETED
797
+	 *  (just to give us a change at racing with timer_routine, if 
798
+	 *  TIMER_DELETED is set and the fr handle is not already executing =>
799
+	 *   it will not be called anymore)
800
+	 */
801
+	if (tl->timer_list!=DETACHED_LIST){
802
+		remove_timer_unsafe(tl); /* safe to call for null list */
803
+	}else{
804
+		reset_timer(tl);
805
+	}
806
+	unlock(timertable->timers[FR_TIMER_LIST].mutex);
807
+}
808
+
809
+
781 810
 
782 811
 /* determine timer length and put on a correct timer list
783 812
  * WARNING: - don't try to use it to "move" a timer from one list
... ...
@@ -109,6 +109,8 @@ struct timer_link  *check_and_split_time_list( struct timer*, int);
109 109
 */
110 110
 
111 111
 void reset_timer( struct timer_link* tl );
112
+/* remove a timer from FR_TIMER_LIST or FR_INV_TIMER_LIST */
113
+void del_fr_timer( struct timer_link *tl);
112 114
 /* determine timer length and put on a correct timer list */
113 115
 void set_timer( struct timer_link *new_tl, enum lists list_id, unsigned int* ext_timeout );
114 116
 /* similar to set_timer, except it allows only one-time
... ...
@@ -264,10 +264,14 @@ error:
264 264
 void free_rdata_list(struct rdata* head)
265 265
 {
266 266
 	struct rdata* l;
267
-	for(l=head; l; l=l->next){
267
+	struct rdata* next_l;
268
+	l=head;
269
+	while (l != 0) {
270
+		next_l = l->next;
268 271
 		/* free the parsed rdata*/
269 272
 		if (l->rdata) local_free(l->rdata);
270 273
 		local_free(l);
274
+		l = next_l;
271 275
 	}
272 276
 }
273 277