Merge branch 'rpc_async'
[sip-router] / modules / tm / h_table.c
index 909a1bc..51f9005 100644 (file)
@@ -142,7 +142,13 @@ void free_cell( struct cell* dead_cell )
                cbs_tmp = cbs;
                cbs = cbs->next;
                if (cbs_tmp->release) {
+                       /* It is safer to release the shm memory lock
+                        * otherwise the release function must to be aware of
+                        * the lock state (Miklos)
+                        */
+                       shm_unlock();
                        cbs_tmp->release(cbs_tmp->param);
+                       shm_lock();
                }
                shm_free_unsafe( cbs_tmp );
        }
@@ -266,6 +272,7 @@ struct cell*  build_cell( struct sip_msg* p_msg )
        struct cell* new_cell;
        int          sip_msg_len;
        avp_list_t* old;
+       struct tm_callback *cbs, *cbs_tmp;
 
        /* allocs a new cell */
        /* if syn_branch==0 add space for md5 (MD5_LEN -sizeof(struct cell.md5)) */
@@ -343,6 +350,24 @@ struct cell*  build_cell( struct sip_msg* p_msg )
        return new_cell;
 
 error:
+       /* Other modules may have already registered some
+        * transaction callbacks and may also allocated
+        * additional memory for their parameters,
+        * hence TMCB_DESTROY needs to be called. (Miklos)
+        */
+       if (unlikely(has_tran_tmcbs(new_cell, TMCB_DESTROY)))
+               run_trans_callbacks(TMCB_DESTROY, new_cell, 0, 0, 0);
+
+       /* free the callback list */
+       for( cbs=(struct tm_callback*)new_cell->tmcb_hl.first ; cbs ; ) {
+               cbs_tmp = cbs;
+               cbs = cbs->next;
+               if (cbs_tmp->release) {
+                       cbs_tmp->release(cbs_tmp->param);
+               }
+               shm_free( cbs_tmp );
+       }
+       
        destroy_avp_list(&new_cell->user_avps_from);
        destroy_avp_list(&new_cell->user_avps_to);
        destroy_avp_list(&new_cell->uri_avps_from);