--- apps/app_confbridge.c.orig 2012-05-03 15:57:57.400247203 -0600 +++ apps/app_confbridge.c 2012-05-03 19:28:16.688791477 -0600 @@ -610,9 +610,10 @@ } else if (conference_bridge->users == 2) { if (conference_bridge_user) { /* Eep, there is one other person */ - if (ast_stream_and_wait(conference_bridge_user->chan, + int res = ast_stream_and_wait(conference_bridge_user->chan, only_one, - "")) { + ""); + if (res) { return -1; } } else { @@ -742,21 +743,24 @@ */ static int turn_off_moh(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) { + int success = 0; if (conference_bridge_user->playing_moh) { if (!conference_bridge_user->forced_moh) { + ast_mutex_lock(&conference_bridge_user->suspend_lock); if (!ast_bridge_suspend(conference_bridge->bridge, conference_bridge_user->chan)) { conference_bridge_user->playing_moh = 0; ast_moh_stop(conference_bridge_user->chan); ast_bridge_unsuspend(conference_bridge->bridge, conference_bridge_user->chan); conference_bridge_user->features.mute = conference_bridge_user->forced_mute; } else { - return -1; + success = -1; } + ast_mutex_unlock(&conference_bridge_user->suspend_lock); } else { conference_bridge_user->playing_moh = 0; } } - return 0; + return success; } /*! @@ -1190,12 +1194,14 @@ } } if (!other_participant->playing_moh && !other_participant->forced_moh) { + ast_mutex_lock(&other_participant->suspend_lock); if (!ast_bridge_suspend(conference_bridge->bridge, other_participant->chan)) { ast_moh_start(other_participant->chan, other_participant->u_profile.moh_class, NULL); other_participant->playing_moh = 1; other_participant->features.mute = 1; ast_bridge_unsuspend(conference_bridge->bridge, other_participant->chan); } + ast_mutex_unlock(&other_participant->suspend_lock); } } } @@ -1435,6 +1441,7 @@ .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD, .tech_args.drop_silence = 0, }; + ast_mutex_init(&conference_bridge_user.suspend_lock); AST_DECLARE_APP_ARGS(args, AST_APP_ARG(conf_name); AST_APP_ARG(b_profile_name); @@ -1640,9 +1647,11 @@ /* If the user was kicked from the conference play back the audio prompt for it */ if (!quiet && conference_bridge_user.kicked) { + ast_mutex_lock(&conference_bridge_user.suspend_lock); res = ast_stream_and_wait(chan, conf_get_sound(CONF_SOUND_KICKED, conference_bridge_user.b_profile.sounds), ""); + ast_mutex_unlock(&conference_bridge_user.suspend_lock); } /* Restore volume adjustments to previous values in case they were changed */ @@ -1660,6 +1669,7 @@ confbridge_cleanup: ast_bridge_features_cleanup(&conference_bridge_user.features); conf_bridge_profile_destroy(&conference_bridge_user.b_profile); + ast_mutex_destroy(&conference_bridge_user.suspend_lock); return res; } @@ -1673,10 +1683,11 @@ conference_bridge_user->forced_mute = conference_bridge_user->features.mute; ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(chan), conference_bridge_user->features.mute ? "muted" : "unmuted", conference_bridge_user->b_profile.name, ast_channel_name(chan)); } - return ast_stream_and_wait(chan, (conference_bridge_user->features.mute ? + int res = ast_stream_and_wait(chan, (conference_bridge_user->features.mute ? conf_get_sound(CONF_SOUND_MUTED, conference_bridge_user->b_profile.sounds) : conf_get_sound(CONF_SOUND_UNMUTED, conference_bridge_user->b_profile.sounds)), ""); + return res; } static int action_toggle_mute_participants(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) @@ -1741,7 +1752,8 @@ char *file = NULL; while ((file = strsep(&file_copy, "&"))) { - if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) { + int res = ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan)); + if (res) { ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file); return -1; } @@ -1950,7 +1962,6 @@ conf_get_sound(CONF_SOUND_LOCKED_NOW, conference_bridge_user->b_profile.sounds) : conf_get_sound(CONF_SOUND_UNLOCKED_NOW, conference_bridge_user->b_profile.sounds)), ""); - break; case MENU_ACTION_ADMIN_KICK_LAST: res |= action_kick_last(conference_bridge, bridge_channel, conference_bridge_user); @@ -2191,15 +2202,19 @@ if (participant) { if (!participant->playing_moh) { /* If the participant is playing MoH naturally, let it do its thing */ if (moh && !participant->forced_moh) { + ast_mutex_lock(&participant->suspend_lock); if (!ast_bridge_suspend(bridge->bridge, participant->chan)) { ast_moh_start(participant->chan, participant->u_profile.moh_class, NULL); ast_bridge_unsuspend(bridge->bridge, participant->chan); } + ast_mutex_unlock(&participant->suspend_lock); } else if (!moh && participant->forced_moh) { + ast_mutex_lock(&participant->suspend_lock); if (!ast_bridge_suspend(bridge->bridge, participant->chan)) { ast_moh_stop(participant->chan); ast_bridge_unsuspend(bridge->bridge, participant->chan); - } + } + ast_mutex_unlock(&participant->suspend_lock); } } /* Set flags regardless of natural state */ @@ -2322,8 +2337,9 @@ static void *action_confbridgeplayfile_thread(void *obj) { struct action_confbridgeplayfile_specifier *specifier = (struct action_confbridgeplayfile_specifier *)obj; - + if (specifier->participant) { + ast_mutex_lock(&specifier->participant->suspend_lock); if (!ast_bridge_suspend(specifier->bridge->bridge, specifier->participant->chan)) { if(specifier->participant->playing_moh || specifier->participant->forced_moh){ ast_moh_stop(specifier->participant->chan); @@ -2338,6 +2354,7 @@ } ast_bridge_unsuspend(specifier->bridge->bridge, specifier->participant->chan); } + ast_mutex_unlock(&specifier->participant->suspend_lock); } else { play_sound_helper(specifier->bridge, (const char *)&specifier->file, 0); } --- apps/confbridge/include/confbridge.h.orig 2012-05-03 18:42:51.772673952 -0600 +++ apps/confbridge/include/confbridge.h 2012-05-03 19:16:02.116759795 -0600 @@ -232,6 +232,7 @@ unsigned int forced_moh:1; /*!< The user has been explicitly placed on hold and should not be subject to automatic toggles */ unsigned int forced_mute:1; /*!< The user has been explicitly placed on hold and should not be subject to automatic toggles */ AST_LIST_ENTRY(conference_bridge_user) list; /*!< Linked list information */ + ast_mutex_t suspend_lock; /*!< Lock used to prevent channel-suspensions from encountering race conditions */ }; /*! \brief load confbridge.conf file */