Browse Source

tm: force free cell in UNREF_FREE() if transaction is unlinkled from timers

Daniel-Constantin Mierla 7 years ago
parent
commit
72f5eaeeef
4 changed files with 33 additions and 5 deletions
  1. 8 3
      src/modules/tm/t_funcs.h
  2. 5 1
      src/modules/tm/timer.c
  3. 19 0
      src/modules/tm/timer.h
  4. 1 1
      src/modules/tm/uac.c

+ 8 - 3
src/modules/tm/t_funcs.h

@@ -96,13 +96,18 @@ int send_pr_buffer( struct retr_buf *rb, void *buf, int len);
 
 #ifdef TM_DEL_UNREF
 
-#define UNREF_FREE(_T_cell) \
+#define UNREF_FREE(_T_cell, _T_unlinked) \
 	do{\
 		if (atomic_dec_and_test(&(_T_cell)->ref_count)){ \
 			unlink_timers((_T_cell)); \
 			free_cell((_T_cell)); \
-		}else \
-			t_stats_delayed_free(); \
+		}else{ \
+			if(_T_unlinked){ \
+				free_cell((_T_cell)); \
+			}else{ \
+				t_stats_delayed_free(); \
+			} \
+		} \
 	}while(0)
 
 #define UNREF_NOSTATS(_T_cell) \

+ 5 - 1
src/modules/tm/timer.c

@@ -648,7 +648,11 @@ ticks_t wait_handler(ticks_t ti, struct timer_ln *wait_tl, void *data)
 	remove_from_hash_table_unsafe(p_cell);
 	UNLOCK_HASH(p_cell->hash_index);
 	p_cell->flags |= T_IN_AGONY;
-	UNREF_FREE(p_cell);
+	if(t_linked_timers(p_cell)) {
+		UNREF_FREE(p_cell, 0);
+	} else {
+		UNREF_FREE(p_cell, 1);
+	}
 	ret = 0;
 #else  /* TM_DEL_UNREF */
 	if(p_cell->flags & T_IN_AGONY) {

+ 19 - 0
src/modules/tm/timer.h

@@ -375,5 +375,24 @@ inline static void unlink_timers(struct cell *t)
 	cleanup_localcancel_timers(t);
 }
 
+inline static int t_linked_timers(tm_cell_t *t)
+{
+	int i;
+
+	if(t->uas.response.timer.next!=NULL || t->uas.response.timer.prev!=NULL) {
+		return 1;
+	}
+	for(i = 0; i < t->nr_of_outgoings; i++) {
+		if(t->uac[i].request.timer.next!=NULL
+				|| t->uac[i].request.timer.prev!=NULL) {
+			return 1;
+		}
+		if(t->uac[i].local_cancel.timer.next!=NULL
+				|| t->uac[i].local_cancel.timer.prev!=NULL) {
+			return 1;
+		}
+	}
+	return 0;
+}
 
 #endif

+ 1 - 1
src/modules/tm/uac.c

@@ -589,7 +589,7 @@ error2:
 		if(atomic_get_int(&new_cell->ref_count)==0) {
 			free_cell(new_cell);
 		} else {
-			UNREF_FREE(new_cell);
+			UNREF_FREE(new_cell, 0);
 		}
 	}
 #else