[svn-commits] mjordan: branch 12 r405216 - in /branches/12: ./ apps/ apps/confbridge/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Jan 9 09:49:45 CST 2014


Author: mjordan
Date: Thu Jan  9 09:49:40 2014
New Revision: 405216

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=405216
Log:
app_confbridge: Fix crash caused when waitmarked/marked users leave together

When waitmarked users join a ConfBridge, the conference state is transitioned
from EMPTY -> INACTIVE. In this state, the users are maintined in a waiting
users list. When a marked user joins, the ConfBridge conference transitions
from INACTIVE -> MULTI_MARKED, and all users are put onto the active list of
users. This process works correctly.

When the marked user leaves, if they are the last marked user, the MULTI_MARKED
state does the following:
(1) It plays back a message to the bridge stating that the leader has left the
    conference. This requires an unlocking of the bridge.
(2) It moves waitmarked users back to the waiting list
(3) It transitions to the appropriate state: in this case, INACTIVE

However, because it plays the prompt back to the bridge before moving the users
and before finishing the state transition, this creates a race condition: with
the bridge unlocked, waitmarked users who leave the conference (or are kicked
from it) can cause a state transition of the bridge to another state before
the conference is transitioned to the INACTIVE state. This causes the state
machine to get a bit wonky, often leading to a crash when the MULTI_MARKED state
attempts to conclude its processing.

This patch fixes this problem:
(1) It prevents kicked users from being kicked again. That's just a nicety.
(2) More importantly, it fixes the race condition by only playing the prompt
    once the state has transitioned correctly to INACTIVE. If waitmarked users
    sneak out during the prompt being played, no harm no foul.

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

(closes issue AST-1258)
Reported by: Steve Pitts
........

Merged revisions 405215 from http://svn.asterisk.org/svn/asterisk/branches/11

Modified:
    branches/12/   (props changed)
    branches/12/apps/app_confbridge.c
    branches/12/apps/confbridge/conf_state_multi_marked.c

Propchange: branches/12/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Modified: branches/12/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/apps/app_confbridge.c?view=diff&rev=405216&r1=405215&r2=405216
==============================================================================
--- branches/12/apps/app_confbridge.c (original)
+++ branches/12/apps/app_confbridge.c Thu Jan  9 09:49:40 2014
@@ -1948,7 +1948,7 @@
 		ast_stream_and_wait(bridge_channel->chan,
 			conf_get_sound(CONF_SOUND_ERROR_MENU, user->b_profile.sounds),
 			"");
-	} else if (last_user) {
+	} else if (last_user && !last_user->kicked) {
 		last_user->kicked = 1;
 		ast_bridge_remove(conference->bridge, last_user->chan);
 		ao2_unlock(conference);
@@ -2127,7 +2127,7 @@
 
 	SCOPED_AO2LOCK(bridge_lock, conference);
 	AST_LIST_TRAVERSE(&conference->active_list, user, list) {
-		if (!strcasecmp(ast_channel_name(user->chan), channel)) {
+		if (!strcasecmp(ast_channel_name(user->chan), channel) && !user->kicked) {
 			user->kicked = 1;
 			ast_bridge_remove(conference->bridge, user->chan);
 			return 0;
@@ -2138,7 +2138,7 @@
 		}
 	}
 	AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
-		if (!strcasecmp(ast_channel_name(user->chan), channel)) {
+		if (!strcasecmp(ast_channel_name(user->chan), channel) && !user->kicked) {
 			user->kicked = 1;
 			ast_bridge_remove(conference->bridge, user->chan);
 			return 0;

Modified: branches/12/apps/confbridge/conf_state_multi_marked.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/apps/confbridge/conf_state_multi_marked.c?view=diff&rev=405216&r1=405215&r2=405216
==============================================================================
--- branches/12/apps/confbridge/conf_state_multi_marked.c (original)
+++ branches/12/apps/confbridge/conf_state_multi_marked.c Thu Jan  9 09:49:40 2014
@@ -80,23 +80,16 @@
 static void leave_marked(struct confbridge_user *user)
 {
 	struct confbridge_user *user_iter;
+	int need_prompt = 0;
 
 	conf_remove_user_marked(user->conference, user);
 
 	if (user->conference->markedusers == 0) {
-		/* Play back the audio prompt saying the leader has left the conference */
-		if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET)) {
-			ao2_unlock(user->conference);
-			ast_autoservice_start(user->chan);
-			play_sound_file(user->conference,
-				conf_get_sound(CONF_SOUND_LEADER_HAS_LEFT, user->b_profile.sounds));
-			ast_autoservice_stop(user->chan);
-			ao2_lock(user->conference);
-		}
+		need_prompt = 1;
 
 		AST_LIST_TRAVERSE_SAFE_BEGIN(&user->conference->active_list, user_iter, list) {
-			/* Kick ENDMARKED user_iters */
-			if (ast_test_flag(&user_iter->u_profile, USER_OPT_ENDMARKED)) {
+			/* Kick ENDMARKED cbu_iters */
+			if (ast_test_flag(&user_iter->u_profile, USER_OPT_ENDMARKED) && !user_iter->kicked) {
 				if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED)
 					&& !ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER)) {
 					AST_LIST_REMOVE_CURRENT(list);
@@ -162,6 +155,18 @@
 			break; /* Stay in marked */
 		}
 	}
+
+	if (need_prompt) {
+		/* Play back the audio prompt saying the leader has left the conference */
+		if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET)) {
+			ao2_unlock(user->conference);
+			ast_autoservice_start(user->chan);
+			play_sound_file(user->conference,
+				conf_get_sound(CONF_SOUND_LEADER_HAS_LEFT, user->b_profile.sounds));
+			ast_autoservice_stop(user->chan);
+			ao2_lock(user->conference);
+		}
+	}
 }
 
 static void transition_to_marked(struct confbridge_user *user)




More information about the svn-commits mailing list