[asterisk-commits] russell: trunk r59368 - /trunk/channels/chan_iax2.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Thu Mar 29 11:31:36 MST 2007


Author: russell
Date: Thu Mar 29 13:31:35 2007
New Revision: 59368

URL: http://svn.digium.com/view/asterisk?view=rev&rev=59368
Log:
Fix an issue with hashing iax2 pvt structures that caused random crashes on
systems under heavy load such as IAXtel.
(possibly related to issue #9403)

Modified:
    trunk/channels/chan_iax2.c

Modified: trunk/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_iax2.c?view=diff&rev=59368&r1=59367&r2=59368
==============================================================================
--- trunk/channels/chan_iax2.c (original)
+++ trunk/channels/chan_iax2.c Thu Mar 29 13:31:35 2007
@@ -473,6 +473,8 @@
 	int dropped;
 	int ooo;
 };
+
+struct iax2_pvt_ref;
 
 struct chan_iax2_pvt {
 	/*! Socket to send/receive on for this call */
@@ -632,14 +634,19 @@
 	int frames_dropped;
 	/*! received frame count: (just for stats) */
 	int frames_received;
-
-	AST_LIST_ENTRY(chan_iax2_pvt) entry;
+	struct iax2_pvt_ref *hash_ref;
 	unsigned short hash;
 };
 
+struct iax2_pvt_ref {
+	struct chan_iax2_pvt *pvt;
+	unsigned int callno;
+	AST_LIST_ENTRY(iax2_pvt_ref) entry;
+};
+
 /* Somewhat arbitrary prime number */
-#define PVT_HASH_SIZE 563
-static AST_RWLIST_HEAD(pvt_list, chan_iax2_pvt) pvt_hash_tbl[PVT_HASH_SIZE];
+#define PVT_HASH_SIZE 3373
+static AST_RWLIST_HEAD(pvt_list, iax2_pvt_ref) pvt_hash_tbl[PVT_HASH_SIZE];
 
 static AST_LIST_HEAD_STATIC(queue, iax_frame);
 
@@ -1274,16 +1281,21 @@
 
 static inline void hash_on_peer(struct chan_iax2_pvt *pvt)
 {
-	if (pvt->hash) {
+	if (pvt->hash_ref) {
 		AST_RWLIST_WRLOCK(&pvt_hash_tbl[pvt->hash]);
-		AST_RWLIST_REMOVE(&pvt_hash_tbl[pvt->hash], pvt, entry);
+		AST_RWLIST_REMOVE(&pvt_hash_tbl[pvt->hash], pvt->hash_ref, entry);
 		AST_RWLIST_UNLOCK(&pvt_hash_tbl[pvt->hash]);	
+	} else {
+		if (!(pvt->hash_ref = ast_calloc(1, sizeof(pvt->hash_ref))))
+			return;
+		pvt->hash_ref->pvt = pvt;
 	}
 
 	pvt->hash = peer_hash_val(&pvt->addr, pvt->peercallno);
+	pvt->hash_ref->callno = pvt->callno;
 
 	AST_RWLIST_WRLOCK(&pvt_hash_tbl[pvt->hash]);
-	AST_RWLIST_INSERT_HEAD(&pvt_hash_tbl[pvt->hash], pvt, entry);
+	AST_RWLIST_INSERT_HEAD(&pvt_hash_tbl[pvt->hash], pvt->hash_ref, entry);
 	AST_RWLIST_UNLOCK(&pvt_hash_tbl[pvt->hash]);
 }
 
@@ -1295,13 +1307,13 @@
 	char host[80];
 	if (new <= NEW_ALLOW) {
 		unsigned short hash = peer_hash_val(sin, callno);
-		const struct chan_iax2_pvt *pvt;
-		AST_RWLIST_RDLOCK(&pvt_hash_tbl[hash]);
-		AST_RWLIST_TRAVERSE(&pvt_hash_tbl[hash], pvt, entry) {
-			ast_mutex_lock(&iaxsl[pvt->callno]);
-			if (match(sin, callno, dcallno, pvt))
-				res = pvt->callno;
-			ast_mutex_unlock(&iaxsl[pvt->callno]);
+		struct iax2_pvt_ref *pvt_ref;
+		AST_RWLIST_WRLOCK(&pvt_hash_tbl[hash]);
+		AST_RWLIST_TRAVERSE(&pvt_hash_tbl[hash], pvt_ref, entry) {
+			ast_mutex_lock(&iaxsl[pvt_ref->callno]);
+			if (match(sin, callno, dcallno, pvt_ref->pvt))
+				res = pvt_ref->callno;
+			ast_mutex_unlock(&iaxsl[pvt_ref->callno]);
 			if (res > 0)
 				break;
  		}
@@ -1844,10 +1856,11 @@
 			pvt->owner = NULL;
 		iax2_destroy_helper(pvt);
 
-		if (pvt->hash) {
+		if (pvt->hash_ref) {
 			AST_RWLIST_WRLOCK(&pvt_hash_tbl[pvt->hash]);
-			AST_RWLIST_REMOVE(&pvt_hash_tbl[pvt->hash], pvt, entry);
+			AST_RWLIST_REMOVE(&pvt_hash_tbl[pvt->hash], pvt->hash_ref, entry);
 			AST_RWLIST_UNLOCK(&pvt_hash_tbl[pvt->hash]);
+			free(pvt->hash_ref);
 		}
 
 		/* Already gone */



More information about the asterisk-commits mailing list