]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
fix race condition where a transferring leg could be hungup on by the bridge partner...
authorAnthony Minessale <anthm@freeswitch.org>
Fri, 28 Feb 2014 02:15:47 +0000 (07:15 +0500)
committerAnthony Minessale <anthm@freeswitch.org>
Fri, 28 Feb 2014 02:16:05 +0000 (07:16 +0500)
src/switch_ivr_bridge.c

index 87ceeba3e5e9fa386d764e8c9954e69e299ffa8a..f087092e6996a92659ff41bf7ff86c4e9609d356 100644 (file)
@@ -190,6 +190,8 @@ struct switch_ivr_bridge_data {
        switch_input_callback_function_t input_callback;
        void *session_data;
        int clean_exit;
+       int done;
+       struct switch_ivr_bridge_data *other_leg_data;
 };
 typedef struct switch_ivr_bridge_data switch_ivr_bridge_data_t;
 
@@ -349,6 +351,9 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
                }
 
                if (!switch_channel_ready(chan_a)) {
+                       if (switch_channel_up(chan_a)) {
+                               data->clean_exit = 1;
+                       }
                        goto end_of_bridge_loop;
                }
 
@@ -634,7 +639,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
        switch_channel_clear_flag(chan_a, CF_BRIDGED);
        
        if (switch_channel_test_flag(chan_a, CF_LEG_HOLDING) || switch_channel_test_flag(chan_a, CF_HANGUP_HELD)) {
-               if (switch_channel_ready(chan_b) && switch_channel_get_state(chan_b) != CS_PARK) {
+               if (switch_channel_ready(chan_b) && switch_channel_get_state(chan_b) != CS_PARK && !data->other_leg_data->clean_exit) {
                        const char *ext = switch_channel_get_variable(chan_a, "hold_hangup_xfer_exten");
                        
                        switch_channel_stop_broadcast(chan_b);
@@ -661,6 +666,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
 
 
        switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
+       data->done = 1;
        switch_core_session_rwunlock(session_b);
        return NULL;
 }
@@ -1299,6 +1305,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
        b_leg->input_callback = input_callback;
        b_leg->session_data = peer_session_data;
        b_leg->clean_exit = 0;
+       b_leg->other_leg_data = a_leg;
 
        a_leg->session = session;
        switch_copy_string(a_leg->b_uuid, switch_core_session_get_uuid(peer_session), sizeof(a_leg->b_uuid));
@@ -1306,6 +1313,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
        a_leg->input_callback = input_callback;
        a_leg->session_data = session_data;
        a_leg->clean_exit = 0;
+       a_leg->other_leg_data = b_leg;
 
        switch_channel_add_state_handler(peer_channel, &audio_bridge_peer_state_handlers);