[asterisk-commits] alecdavis: branch 1.8 r308945 - /branches/1.8/channels/chan_sip.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Feb 25 12:53:01 CST 2011


Author: alecdavis
Date: Fri Feb 25 12:52:53 2011
New Revision: 308945

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=308945
Log:
Fix Deadlock with attended transfer of SIP call

Call path 
  sip_set_rtp_peer (locks chan then pvt)
   transmit_reinvite_with_sdp
    try_suggested_sip_codec
     pbx_builtin_getvar_helper (locks p->owner)

But by the time p->owner lock was attempted, seems as though chan and p->owner were different.

So in sip_set_rtp_peer, lock pvt first then lock p->owner using deadlocking methods.

(closes issue #18837)
Reported by: alecdavis
Patches: 
      bug18837-trunk.diff3.txt uploaded by alecdavis (license 585)
Tested by: alecdavis, Irontec, ZX81, cmaj

Review: [https://reviewboard.asterisk.org/r/1126/]


Modified:
    branches/1.8/channels/chan_sip.c

Modified: branches/1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/channels/chan_sip.c?view=diff&rev=308945&r1=308944&r2=308945
==============================================================================
--- branches/1.8/channels/chan_sip.c (original)
+++ branches/1.8/channels/chan_sip.c Fri Feb 25 12:52:53 2011
@@ -27615,7 +27615,20 @@
 	if (!p) {
 		return -1;
 	}
+	/*
+	 * Lock both the pvt and it's owner safely.
+	 */
 	sip_pvt_lock(p);
+	while (p->owner && ast_channel_trylock(p->owner)) {
+		sip_pvt_unlock(p);
+		usleep(1);
+		sip_pvt_lock(p);
+	}
+
+	if (!p->owner) {
+		sip_pvt_unlock(p);
+		return 0;
+	}
 	if (udptl) {
 		ast_udptl_get_peer(udptl, &p->udptlredirip);
 	} else {
@@ -27634,6 +27647,7 @@
 	}
 	/* Reset lastrtprx timer */
 	p->lastrtprx = p->lastrtptx = time(NULL);
+	ast_channel_unlock(p->owner);
 	sip_pvt_unlock(p);
 	return 0;
 }
@@ -27750,12 +27764,25 @@
 	if (!ast_bridged_channel(chan) && !sip_cfg.directrtpsetup) 	/* We are in early state */
 		return 0;
 
-	ast_channel_lock(chan);
+	/*
+	 * Lock both the pvt and it's owner safely.
+	 */
 	sip_pvt_lock(p);
+	while (p->owner && ast_channel_trylock(p->owner)) {
+		sip_pvt_unlock(p);
+		usleep(1);
+		sip_pvt_lock(p);
+	}
+
+	if (!p->owner) {
+		sip_pvt_unlock(p);
+		return 0;
+	}
+
 	if (p->alreadygone) {
 		/* If we're destroyed, don't bother */
+		ast_channel_unlock(p->owner);
 		sip_pvt_unlock(p);
-		ast_channel_unlock(chan);
 		return 0;
 	}
 
@@ -27763,8 +27790,8 @@
 	   that are known to be behind a NAT, then stop the process now
 	*/
 	if (nat_active && !ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA_NAT)) {
+		ast_channel_unlock(p->owner);
 		sip_pvt_unlock(p);
-		ast_channel_unlock(chan);
 		return 0;
 	}
 
@@ -27806,8 +27833,8 @@
 	}
 	/* Reset lastrtprx timer */
 	p->lastrtprx = p->lastrtptx = time(NULL);
+	ast_channel_unlock(p->owner);
 	sip_pvt_unlock(p);
-	ast_channel_unlock(chan);
 	return 0;
 }
 




More information about the asterisk-commits mailing list