[asterisk-commits] rmudgett: branch group/bridge_construction r382358 - in /team/group/bridge_co...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Mar 1 18:08:00 CST 2013


Author: rmudgett
Date: Fri Mar  1 18:07:57 2013
New Revision: 382358

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=382358
Log:
Fix race condition causing third channel in transition to three party bridges to wait in the wrong threading mode.

Modified:
    team/group/bridge_construction/include/asterisk/bridging.h
    team/group/bridge_construction/main/bridging.c

Modified: team/group/bridge_construction/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/include/asterisk/bridging.h?view=diff&rev=382358&r1=382357&r2=382358
==============================================================================
--- team/group/bridge_construction/include/asterisk/bridging.h (original)
+++ team/group/bridge_construction/include/asterisk/bridging.h Fri Mar  1 18:07:57 2013
@@ -144,6 +144,8 @@
 	pthread_t thread;
 	/*! Additional file descriptors to look at */
 	int fds[4];
+	/*! TRUE if the channel has been poked. */
+	unsigned int poked;
 	/*! TRUE if the channel is in a bridge. */
 	unsigned int in_bridge:1;
 	/*! TRUE if the channel just joined the bridge. */

Modified: team/group/bridge_construction/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/main/bridging.c?view=diff&rev=382358&r1=382357&r2=382358
==============================================================================
--- team/group/bridge_construction/main/bridging.c (original)
+++ team/group/bridge_construction/main/bridging.c Fri Mar  1 18:07:57 2013
@@ -138,6 +138,7 @@
 void ast_bridge_channel_poke(struct ast_bridge_channel *bridge_channel)
 {
 	if (!pthread_equal(pthread_self(), bridge_channel->thread)) {
+		bridge_channel->poked = 1;
 		pthread_kill(bridge_channel->thread, SIGURG);
 		ast_cond_signal(&bridge_channel->cond);
 	}
@@ -1287,27 +1288,31 @@
 
 	/* Wait for data to either come from the channel or us to be signaled */
 	ao2_lock(bridge_channel);
-	if (bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_WAIT) {
-		ao2_unlock(bridge_channel);
-		ao2_lock(bridge_channel->bridge);
+	if (bridge_channel->poked
+		|| bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_WAIT) {
 	} else if (bridge_channel->suspended) {
 		ast_debug(1, "Going into a multithreaded signal wait for bridge channel %p(%s) of bridge %p\n",
 			bridge_channel, ast_channel_name(bridge_channel->chan),
 			bridge_channel->bridge);
 		ast_cond_wait(&bridge_channel->cond, ao2_object_get_lockaddr(bridge_channel));
-		ao2_unlock(bridge_channel);
-		ao2_lock(bridge_channel->bridge);
 	} else {
-		ao2_unlock(bridge_channel);
 		ast_debug(10, "Going into a multithreaded waitfor for bridge channel %p(%s) of bridge %p\n",
 			bridge_channel, ast_channel_name(bridge_channel->chan),
 			bridge_channel->bridge);
+		ao2_unlock(bridge_channel);
 		chan = ast_waitfor_nandfds(&bridge_channel->chan, 1, fds, nfds, NULL, &outfd, &ms);
 		ao2_lock(bridge_channel->bridge);
 		if (!bridge_channel->suspended) {
 			ast_bridge_handle_trip(bridge_channel->bridge, bridge_channel, chan, outfd);
 		}
-	}
+		ao2_lock(bridge_channel);
+		bridge_channel->poked = 0;
+		ao2_unlock(bridge_channel);
+		return;
+	}
+	bridge_channel->poked = 0;
+	ao2_unlock(bridge_channel);
+	ao2_lock(bridge_channel->bridge);
 }
 
 /*! \brief Run in a singlethreaded model. Each joined channel yields itself to the main bridge thread. TODO: Improve */
@@ -1315,12 +1320,14 @@
 {
 	ao2_unlock(bridge_channel->bridge);
 	ao2_lock(bridge_channel);
-	if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
+	if (!bridge_channel->poked
+		&& bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
 		ast_debug(1, "Going into a single threaded signal wait for bridge channel %p(%s) of bridge %p\n",
 			bridge_channel, ast_channel_name(bridge_channel->chan),
 			bridge_channel->bridge);
 		ast_cond_wait(&bridge_channel->cond, ao2_object_get_lockaddr(bridge_channel));
 	}
+	bridge_channel->poked = 0;
 	ao2_unlock(bridge_channel);
 	ao2_lock(bridge_channel->bridge);
 }




More information about the asterisk-commits mailing list