[asterisk-commits] russell: branch 1.4 r81832 - /branches/1.4/channels/chan_sip.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Sep 6 17:28:57 CDT 2007


Author: russell
Date: Thu Sep  6 17:28:57 2007
New Revision: 81832

URL: http://svn.digium.com/view/asterisk?view=rev&rev=81832
Log:
(closes issue #9724, closes issue #10374)
Reported by: kenw
Patches:
      9724.txt uploaded by russell (license 2)
Tested by: kenw, russell

Resolve a deadlock that occurs when doing a SIP transfer to parking.  

I come across this type of deadlock fairly often it seems.  It is very important
to mind the boundary between the channel driver and the core in respect to the
channel lock and the channel-pvt lock.  Channel drivers lock to lock the
pvt and then the channel once it calls into the core, while the core will do
it in the opposite order.  The way this is avoided is by having channel drivers
either release their pvt lock while calling into the core, or such as in this
case, unlocking the pvt just long enough to acquire the channel lock.

Modified:
    branches/1.4/channels/chan_sip.c

Modified: branches/1.4/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/channels/chan_sip.c?view=diff&rev=81832&r1=81831&r2=81832
==============================================================================
--- branches/1.4/channels/chan_sip.c (original)
+++ branches/1.4/channels/chan_sip.c Thu Sep  6 17:28:57 2007
@@ -12873,8 +12873,17 @@
 	transferer->readformat = chan2->readformat;
 	transferer->writeformat = chan2->writeformat;
 
-	/* Prepare for taking over the channel */
+	/* Prepare for taking over the channel.  Go ahead and grab this channel
+	 * lock here to avoid a deadlock with callbacks into the channel driver
+	 * that hold the channel lock and want the pvt lock.  */
+	while (ast_channel_trylock(chan2)) {
+		struct sip_pvt *pvt = chan2->tech_pvt;
+		ast_mutex_unlock(&pvt->lock);
+		usleep(1);
+		ast_mutex_lock(&pvt->lock);
+	}
 	ast_channel_masquerade(transferer, chan2);
+	ast_channel_unlock(chan2);
 
 	/* Setup the extensions and such */
 	ast_copy_string(transferer->context, chan2->context, sizeof(transferer->context));




More information about the asterisk-commits mailing list