[asterisk-commits] russell: branch 1.4 r79272 - /branches/1.4/channels/chan_iax2.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Aug 13 14:27:40 CDT 2007


Author: russell
Date: Mon Aug 13 14:27:39 2007
New Revision: 79272

URL: http://svn.digium.com/view/asterisk?view=rev&rev=79272
Log:
I am fighting deadlocks in chan_iax2.  I have tracked them down to a single
core issue.  You can not call find_callno() while holding a pvt lock as this
function has to lock another (every) other pvt lock.  Doing so can lead to a
classic deadlock.  So, I am tracking down all of the code paths where this
can happen and fixing them.

The fix I committed earlier today was along the same theme.  This patch fixes
some code down the path of authenticate_reply.

Modified:
    branches/1.4/channels/chan_iax2.c

Modified: branches/1.4/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/channels/chan_iax2.c?view=diff&rev=79272&r1=79271&r2=79272
==============================================================================
--- branches/1.4/channels/chan_iax2.c (original)
+++ branches/1.4/channels/chan_iax2.c Mon Aug 13 14:27:39 2007
@@ -1244,6 +1244,9 @@
 	return res;
 }
 
+/*!
+ * \note Calling this function while holding another pvt lock can cause a deadlock.
+ */
 static int find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int lockpeer, int sockfd)
 {
 	int res = 0;
@@ -2502,6 +2505,10 @@
 	return 0;
 }
 
+/*!
+ * \note This function calls reg_source_db -> iax2_poke_peer -> find_callno,
+ *       so do not call this with a pvt lock held.
+ */
 static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
 {
 	struct ast_variable *var;
@@ -5219,6 +5226,10 @@
 	return res;
 }
 
+/*!
+ * \note This function calls realtime_peer -> reg_source_db -> iax2_poke_peer -> find_callno,
+ *       so do not call this function with a pvt lock held.
+ */
 static int authenticate_reply(struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, const char *override, const char *okey)
 {
 	struct iax2_peer *peer = NULL;
@@ -5226,7 +5237,8 @@
 	int res = -1;
 	int authmethods = 0;
 	struct iax_ie_data ied;
-	
+	uint16_t callno = p->callno;
+
 	memset(&ied, 0, sizeof(ied));
 	
 	if (ies->username)
@@ -5263,10 +5275,20 @@
 		if (!peer) {
 			/* We checked our list and didn't find one.  It's unlikely, but possible, 
 			   that we're trying to authenticate *to* a realtime peer */
-			if ((peer = realtime_peer(p->peer, NULL))) {
+			const char *peer_name = ast_strdupa(p->peer);
+			ast_mutex_unlock(&iaxsl[callno]);
+			if ((peer = realtime_peer(peer_name, NULL))) {
+				ast_mutex_lock(&iaxsl[callno]);
+				if (!(p = iaxs[callno]))
+					return -1;
 				res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
 				if (ast_test_flag(peer, IAX_TEMPONLY))
 					destroy_peer(peer);
+			}
+			if (!peer) {
+				ast_mutex_lock(&iaxsl[callno]);
+				if (!(p = iaxs[callno]))
+					return -1;
 			}
 		}
 	}
@@ -7383,6 +7405,10 @@
 					ast_log(LOG_WARNING, 
 						"I don't know how to authenticate %s to %s\n", 
 						ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr));
+				}
+				if (!iaxs[fr->callno]) {
+					ast_mutex_unlock(&iaxsl[fr->callno]);
+					return 1;
 				}
 				break;
 			case IAX_COMMAND_AUTHREP:




More information about the asterisk-commits mailing list