From 65524ea2c157daba297a01987b6407f81039ddcd Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 5 Sep 2018 17:10:26 -0500 Subject: [PATCH] FS-11379: [freeswitch-core] Rare race condition in state machine #resolve --- src/include/switch_types.h | 1 + src/switch_core_session.c | 1 + src/switch_core_state_machine.c | 31 ++++++++++++++----------------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 7ad71768f4..93f50a97a3 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1570,6 +1570,7 @@ typedef enum { CF_PROCESSING_STREAM_CHANGE, CF_STREAM_CHANGED, CF_ARRANGED_BRIDGE, + CF_STATE_REPEAT, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ /* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */ CF_FLAG_MAX diff --git a/src/switch_core_session.c b/src/switch_core_session.c index dec61f3917..23307bf81a 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1439,6 +1439,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_wake_session_thread(switch_c } else { if (switch_channel_state_thread_trylock(session->channel) == SWITCH_STATUS_SUCCESS) { /* We've beat them for sure, as soon as we release this lock, they will be checking their queue on the next line. */ + switch_channel_set_flag(session->channel, CF_STATE_REPEAT); switch_channel_state_thread_unlock(session->channel); } else { /* What luck! The channel has already started going to sleep *after* we checked if we need to wake it up. diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index ca362844e0..500ea3c549 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -690,29 +690,26 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) switch_channel_hangup(session->channel, SWITCH_CAUSE_WRONG_CALL_STATE); } } else { - switch_ivr_parse_all_events(session); + switch_channel_state_thread_lock(session->channel); + switch_ivr_parse_all_events(session); - if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { - switch_channel_state_thread_lock(session->channel); + if (switch_channel_test_flag(session->channel, CF_STATE_REPEAT)) { + switch_channel_clear_flag(session->channel, CF_STATE_REPEAT); + } else if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING); - if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { - switch_ivr_parse_all_events(session); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread sleep state: %s!\n", - switch_channel_get_name(session->channel), - switch_channel_state_name(switch_channel_get_running_state(session->channel))); - switch_thread_cond_wait(session->cond, session->mutex); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread wake state: %s!\n", - switch_channel_get_name(session->channel), - switch_channel_state_name(switch_channel_get_running_state(session->channel))); - - - } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread sleep state: %s!\n", + switch_channel_get_name(session->channel), + switch_channel_state_name(switch_channel_get_running_state(session->channel))); + switch_thread_cond_wait(session->cond, session->mutex); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread wake state: %s!\n", + switch_channel_get_name(session->channel), + switch_channel_state_name(switch_channel_get_running_state(session->channel))); switch_channel_clear_flag(session->channel, CF_THREAD_SLEEPING); - switch_channel_state_thread_unlock(session->channel); } - switch_ivr_parse_all_events(session); + switch_channel_state_thread_unlock(session->channel); + switch_ivr_parse_all_events(session); } }