Module: kamailio
Branch: master
Commit: 48f0e7fc9bd95b509e8fb619d8aafb59c125d2c8
URL: 
https://github.com/kamailio/kamailio/commit/48f0e7fc9bd95b509e8fb619d8aafb59c125d2c8

Author: Morten Tryfoss <[email protected]>
Committer: Daniel-Constantin Mierla <[email protected]>
Date: 2023-11-22T09:37:08+01:00

cdp: Avoid deadlock for callback on diameter timeout

Callback function might do an operation which creates a new transaction,
which will result in a deadlock.

Fixes #3641

---

Modified: src/modules/cdp/transaction.c

---

Diff:  
https://github.com/kamailio/kamailio/commit/48f0e7fc9bd95b509e8fb619d8aafb59c125d2c8.diff
Patch: 
https://github.com/kamailio/kamailio/commit/48f0e7fc9bd95b509e8fb619d8aafb59c125d2c8.patch

---

diff --git a/src/modules/cdp/transaction.c b/src/modules/cdp/transaction.c
index 5680e5b59c6..bba7e27fcc8 100644
--- a/src/modules/cdp/transaction.c
+++ b/src/modules/cdp/transaction.c
@@ -206,6 +206,15 @@ void cdp_free_trans(cdp_trans_t *x)
 int cdp_trans_timer(time_t now, void *ptr)
 {
        cdp_trans_t *x, *n;
+       cdp_trans_list_t *cb_queue = 0;
+       cb_queue = pkg_malloc(sizeof(cdp_trans_list_t));
+       if(!cb_queue) {
+               LOG_NO_MEM("pkg", sizeof(cdp_trans_list_t));
+               return 0;
+       }
+       cb_queue->head = 0;
+       cb_queue->tail = 0;
+
        lock_get(trans_list->lock);
        x = trans_list->head;
        while(x) {
@@ -215,9 +224,6 @@ int cdp_trans_timer(time_t now, void *ptr)
                                                        .timeout); 
//Transaction has timed out waiting for response
 
                        x->ans = 0;
-                       if(x->cb) {
-                               (x->cb)(1, *(x->ptr), 0, (now - x->expires));
-                       }
                        n = x->next;
 
                        if(x->prev)
@@ -228,7 +234,17 @@ int cdp_trans_timer(time_t now, void *ptr)
                                x->next->prev = x->prev;
                        else
                                trans_list->tail = x->prev;
-                       if(x->auto_drop)
+
+                       if(x->cb) {
+                               /* queue cb to be done after list unlock */
+                               x->next = 0;
+                               x->prev = cb_queue->tail;
+                               if(cb_queue->tail)
+                                       cb_queue->tail->next = x;
+                               cb_queue->tail = x;
+                               if(!cb_queue->head)
+                                       cb_queue->head = x;
+                       } else if(x->auto_drop) /* if no callback, auto drop 
here */
                                cdp_free_trans(x);
 
                        x = n;
@@ -236,6 +252,17 @@ int cdp_trans_timer(time_t now, void *ptr)
                        x = x->next;
        }
        lock_release(trans_list->lock);
+
+       /* do all queued callbacks */
+       x = cb_queue->head;
+       while(x) {
+               (x->cb)(1, *(x->ptr), 0, (now - x->expires));
+               if(x->auto_drop)
+                       cdp_free_trans(x);
+               x = x->next;
+       }
+       pkg_free(cb_queue);
+
        return 1;
 }
 

_______________________________________________
Kamailio (SER) - Development Mailing List
To unsubscribe send an email to [email protected]

Reply via email to