[asterisk-commits] russell: trunk r354494 - in /trunk: ./ main/channel.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Feb 8 20:28:32 CST 2012


Author: russell
Date: Wed Feb  8 20:28:18 2012
New Revision: 354494

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=354494
Log:
Remove some unnecessary locking from ast_hangup().

This patch removes some unnecessary locking of the channels container in
ast_hangup().  The reason this came up is that this lock can very quickly block
the entire system.  If any of the channel cleanup code decides to block, it
causes a problem for the whole system.  For example, when audiohooks get
destroyed, if that blocks for a while waiting on the mixmonitor thread to exit
because it's busy blocking on some I/O, it causes a problem for many other
threads in the meantime.

Review: https://reviewboard.asterisk.org/r/1712/
........

Merged revisions 354492 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 354493 from http://svn.asterisk.org/svn/asterisk/branches/10

Modified:
    trunk/   (props changed)
    trunk/main/channel.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-10-merged' - no diff available.

Modified: trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel.c?view=diff&rev=354494&r1=354493&r2=354494
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Wed Feb  8 20:28:18 2012
@@ -2570,21 +2570,25 @@
 	}
 }
 
-/*! \brief Hangup a channel */
-int ast_hangup(struct ast_channel *chan)
-{
-	char extra_str[64]; /* used for cel logging below */
-
-	ast_autoservice_stop(chan);
-
-	ao2_lock(channels);
-	ast_channel_lock(chan);
-
+static void destroy_hooks(struct ast_channel *chan)
+{
 	if (chan->audiohooks) {
 		ast_audiohook_detach_list(chan->audiohooks);
 		chan->audiohooks = NULL;
 	}
+
 	ast_framehook_list_destroy(chan);
+}
+
+/*! \brief Hangup a channel */
+int ast_hangup(struct ast_channel *chan)
+{
+	char extra_str[64]; /* used for cel logging below */
+	int was_zombie;
+
+	ast_autoservice_stop(chan);
+
+	ast_channel_lock(chan);
 
 	/*
 	 * Do the masquerade if someone is setup to masquerade into us.
@@ -2596,16 +2600,13 @@
 	 */
 	while (chan->masq) {
 		ast_channel_unlock(chan);
-		ao2_unlock(channels);
 		if (ast_do_masquerade(chan)) {
 			ast_log(LOG_WARNING, "Failed to perform masquerade\n");
 
 			/* Abort the loop or we might never leave. */
-			ao2_lock(channels);
 			ast_channel_lock(chan);
 			break;
 		}
-		ao2_lock(channels);
 		ast_channel_lock(chan);
 	}
 
@@ -2616,13 +2617,20 @@
 		 * to free it later.
 		 */
 		ast_set_flag(chan, AST_FLAG_ZOMBIE);
+		destroy_hooks(chan);
 		ast_channel_unlock(chan);
-		ao2_unlock(channels);
 		return 0;
 	}
 
+	if (!(was_zombie = ast_test_flag(chan, AST_FLAG_ZOMBIE))) {
+		ast_set_flag(chan, AST_FLAG_ZOMBIE);
+	}
+
+	ast_channel_unlock(chan);
 	ao2_unlink(channels, chan);
-	ao2_unlock(channels);
+	ast_channel_lock(chan);
+
+	destroy_hooks(chan);
 
 	free_translation(chan);
 	/* Close audio stream */
@@ -2657,14 +2665,9 @@
 			(long) pthread_self(), ast_channel_name(chan), (long)chan->blocker, chan->blockproc);
 		ast_assert(ast_test_flag(chan, AST_FLAG_BLOCKING) == 0);
 	}
-	if (!ast_test_flag(chan, AST_FLAG_ZOMBIE)) {
+	if (!was_zombie) {
 		ast_debug(1, "Hanging up channel '%s'\n", ast_channel_name(chan));
 
-		/*
-		 * This channel is now dead so mark it as a zombie so anyone
-		 * left holding a reference to this channel will not use it.
-		 */
-		ast_set_flag(chan, AST_FLAG_ZOMBIE);
 		if (chan->tech->hangup) {
 			chan->tech->hangup(chan);
 		}




More information about the asterisk-commits mailing list