[asterisk-commits] russell: trunk r251137 - /trunk/channels/chan_sip.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Mar 6 08:16:25 CST 2010


Author: russell
Date: Sat Mar  6 08:16:20 2010
New Revision: 251137

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=251137
Log:
Fix a crash in SIP blind transfer handling found by an automated external test.

The first real test added to the external test suite found a pretty nasty crash
that occurred in Asterisk trunk.  The crash was due to a race condition between
the REFER handling and channel destruction in the channel thread.  After the
transfer has been completed, we go back to the transferrer channel and try to
lock it so we can fire off a CEL event.  However, there was no guarantee that
the channel was still around at that point since it's racing against the channel
thread.

Since ast_channel is a reference counted object, the fix is simple.  The code
unlocks the transferrer channel before finally completing the transfer with
an async goto.  At this point the channel thread is going to start call tear
down and the channel will eventually be destroyed.  To ensure that the channel
is valid when we want to fire off the CEL event, increase the channel's
reference count.

Modified:
    trunk/channels/chan_sip.c

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=251137&r1=251136&r2=251137
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Sat Mar  6 08:16:20 2010
@@ -20089,6 +20089,11 @@
 	/* Must release lock now, because it will not longer
 	   be accessible after the transfer! */
 	*nounlock = 1;
+	/*
+	 * Increase ref count so that we can delay channel destruction until after
+	 * we get a chance to fire off some events.
+	 */
+	ast_channel_ref(current.chan1);
 	ast_channel_unlock(current.chan1);
 
 	/* Connect the call */
@@ -20113,6 +20118,7 @@
 		transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable (can't handle one-legged xfers)", TRUE);
 		ast_clear_flag(&p->flags[0], SIP_GOTREFER);	
 		append_history(p, "Xfer", "Refer failed (only bridged calls).");
+		ast_channel_unref(current.chan1);
 		return -1;
 	}
 	ast_set_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER);	/* Delay hangup */
@@ -20163,6 +20169,9 @@
 		ast_clear_flag(&p->flags[0], SIP_GOTREFER);	
 		res = -1;
 	}
+
+	ast_channel_unref(current.chan1);
+
 	return res;
 }
 




More information about the asterisk-commits mailing list