From 8aebe3b9009cc682ed1d1fefb599bef190b47a09 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 11 Jun 2018 12:36:22 +0200 Subject: [PATCH] tm: force free cell in UNREF_FREE() if transaction is unlinkled from timers (cherry picked from commit 72f5eaeeef0239ebd16a2d645b83e83eb1a2b506) --- src/modules/tm/t_funcs.h | 11 ++++++++--- src/modules/tm/timer.c | 6 +++++- src/modules/tm/timer.h | 19 +++++++++++++++++++ src/modules/tm/uac.c | 2 +- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/modules/tm/t_funcs.h b/src/modules/tm/t_funcs.h index bbab42482f3..5c219ca02f1 100644 --- a/src/modules/tm/t_funcs.h +++ b/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) \ diff --git a/src/modules/tm/timer.c b/src/modules/tm/timer.c index 996efbc21cc..b5e43259290 100644 --- a/src/modules/tm/timer.c +++ b/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) { diff --git a/src/modules/tm/timer.h b/src/modules/tm/timer.h index 3bdb16a65a7..5cb6c736a6d 100644 --- a/src/modules/tm/timer.h +++ b/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 diff --git a/src/modules/tm/uac.c b/src/modules/tm/uac.c index 9b2f51b5f68..42e25762d26 100644 --- a/src/modules/tm/uac.c +++ b/src/modules/tm/uac.c @@ -589,7 +589,7 @@ static inline int t_uac_prepare(uac_req_t *uac_r, if(atomic_get_int(&new_cell->ref_count)==0) { free_cell(new_cell); } else { - UNREF_FREE(new_cell); + UNREF_FREE(new_cell, 0); } } #else