[sr-dev] git:master: dialog(k): Reworked dlg_set_timeout_by_profile() code to change dialog

Alex Balashov abalashov at evaristesys.com
Sat Dec 22 03:10:35 CET 2012


Module: sip-router
Branch: master
Commit: c9957ad5bf1b672a2661f4faeb9b781820a1f636
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=c9957ad5bf1b672a2661f4faeb9b781820a1f636

Author: Alex Balashov <abalashov at evaristesys.com>
Committer: Alex Balashov <abalashov at evaristesys.com>
Date:   Fri Dec 21 21:08:39 2012 -0500

dialog(k): Reworked dlg_set_timeout_by_profile() code to change dialog
timeouts outside of a profile lock.

This is in order to avoid deadlock complications arising from lock/ref
count operations upstream.  It appears that when update_dlg_timer()
fails, it does not relinquish control back to the calling function, which
created problems with unreleased profile locks.

---

 modules_k/dialog/dlg_profile.c |   78 ++++++++++++++++++++++++++++++++++------
 1 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/modules_k/dialog/dlg_profile.c b/modules_k/dialog/dlg_profile.c
index 41802ea..5b388d8 100644
--- a/modules_k/dialog/dlg_profile.c
+++ b/modules_k/dialog/dlg_profile.c
@@ -714,9 +714,23 @@ int	is_known_dlg(struct sip_msg *msg) {
 int	dlg_set_timeout_by_profile(struct dlg_profile_table *profile, 
 				   str *value, int timeout) 
 {
-	unsigned int		i;
+	unsigned int		i = 0;
+	dlg_cell_t		*this_dlg = NULL;
 	struct dlg_profile_hash	*ph = NULL;
 
+	/* Private structure necessary for manipulating dialog 
+         * timeouts outside of profile locks.  Admittedly, an
+         * ugly hack, but avoids some concurrency issues.
+         */
+
+	struct dlg_map_list {
+		unsigned int		h_id;
+		unsigned int		h_entry;
+		struct dlg_map_list	*next;
+	} *map_head, *map_scan, *map_scan_next;
+
+	map_head = NULL;
+
 	/* If the profile has no value, iterate through every 
 	 * node and set its timeout.
 	 */
@@ -730,11 +744,23 @@ int	dlg_set_timeout_by_profile(struct dlg_profile_table *profile,
 			if(!ph) continue;
 			
 			do { 
-				if(update_dlg_timeout(ph->dlg, timeout) < 0) {
-					lock_release(&profile->lock);
+				struct dlg_map_list *d = malloc(sizeof(struct dlg_map_list));
+
+				if(!d)
 					return -1;
-				}
 
+				memset(d, 0, sizeof(struct dlg_map_list));
+
+				d->h_id = ph->dlg->h_id;
+				d->h_entry = ph->dlg->h_entry;
+
+				if(map_head == NULL)
+					map_head = d;
+				else {
+					d->next = map_head;
+					map_head = d;
+				}
+	
 				ph = ph->next;
 			} while(ph != profile->entries[i].first);
 		} 
@@ -750,15 +776,24 @@ int	dlg_set_timeout_by_profile(struct dlg_profile_table *profile,
 		ph = profile->entries[i].first;
 
 		if(ph) {
-			do { 
-				if(value->len == ph->value.len &&
-				   memcmp(value->s, ph->value.s, 
-					  value->len) == 0) {
+			do {
+				if(ph && value->len == ph->value.len &&
+				   memcmp(value->s, ph->value.s, value->len) == 0) {
+					struct dlg_map_list *d = malloc(sizeof(struct dlg_map_list));
 
-					if(update_dlg_timeout(ph->dlg, 
-							timeout) < 0) {
-						lock_release(&profile->lock);
+					if(!d)
 						return -1;
+
+					memset(d, 0, sizeof(struct dlg_map_list));
+
+					d->h_id = ph->dlg->h_id;
+					d->h_entry = ph->dlg->h_entry;
+
+					if(map_head == NULL)
+						map_head = d;
+					else {
+						d->next = map_head;
+						map_head = d;
 					}
 				}
 
@@ -769,6 +804,27 @@ int	dlg_set_timeout_by_profile(struct dlg_profile_table *profile,
 		lock_release(&profile->lock);
 	}
 
+	/* Walk the list and bulk-set the timeout */
+	
+	for(map_scan = map_head; map_scan != NULL; map_scan = map_scan_next) {
+		map_scan_next = map_scan->next;
+
+		this_dlg = dlg_lookup(map_scan->h_entry, map_scan->h_id);
+
+		if(!this_dlg) {
+			LM_CRIT("Unable to find dialog %d:%d\n", map_scan->h_entry, map_scan->h_id);
+		} else if(this_dlg->state >= DLG_STATE_EARLY) {	
+			if(update_dlg_timeout(this_dlg, timeout) < 0) {
+               			LM_ERR("Unable to set timeout on %d:%d\n", map_scan->h_entry,
+					map_scan->h_id);
+			}
+
+	                dlg_release(this_dlg);
+		}
+
+		free(map_scan);
+	}
+
 	return 0;
 }
 




More information about the sr-dev mailing list