提交 ee7dd033 authored 作者: Anthony Minessale's avatar Anthony Minessale

fix race condition in state thread

上级 31865f0d
...@@ -649,6 +649,7 @@ SWITCH_DECLARE(const char *) switch_channel_get_partner_uuid(switch_channel_t *c ...@@ -649,6 +649,7 @@ SWITCH_DECLARE(const char *) switch_channel_get_partner_uuid(switch_channel_t *c
SWITCH_DECLARE(switch_hold_record_t *) switch_channel_get_hold_record(switch_channel_t *channel); SWITCH_DECLARE(switch_hold_record_t *) switch_channel_get_hold_record(switch_channel_t *channel);
SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel); SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel);
SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel); SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel);
SWITCH_DECLARE(switch_status_t) switch_channel_state_thread_trylock(switch_channel_t *channel);
SWITCH_END_EXTERN_C SWITCH_END_EXTERN_C
#endif #endif
......
...@@ -2288,6 +2288,13 @@ SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel) ...@@ -2288,6 +2288,13 @@ SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel)
switch_mutex_lock(channel->thread_mutex); switch_mutex_lock(channel->thread_mutex);
} }
SWITCH_DECLARE(switch_status_t) switch_channel_state_thread_trylock(switch_channel_t *channel)
{
return switch_mutex_trylock(channel->thread_mutex);
}
SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel) SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel)
{ {
switch_mutex_unlock(channel->thread_mutex); switch_mutex_unlock(channel->thread_mutex);
......
...@@ -927,7 +927,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_message(switch_core_ ...@@ -927,7 +927,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_message(switch_core_
switch_assert(session != NULL); switch_assert(session != NULL);
if (session->message_queue && switch_queue_size(session->message_queue)) { if (session->message_queue) {
if ((status = (switch_status_t) switch_queue_trypop(session->message_queue, &pop)) == SWITCH_STATUS_SUCCESS) { if ((status = (switch_status_t) switch_queue_trypop(session->message_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
*message = (switch_core_session_message_t *) pop; *message = (switch_core_session_message_t *) pop;
if ((*message)->delivery_time && (*message)->delivery_time > switch_epoch_time_now(NULL)) { if ((*message)->delivery_time && (*message)->delivery_time > switch_epoch_time_now(NULL)) {
...@@ -968,7 +968,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_signal_data(switch_cor ...@@ -968,7 +968,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_queue_signal_data(switch_cor
switch_assert(session != NULL); switch_assert(session != NULL);
if (session->signal_data_queue) { if (session->signal_data_queue) {
if (switch_queue_trypush(session->signal_data_queue, signal_data) == SWITCH_STATUS_SUCCESS) { if (switch_queue_push(session->signal_data_queue, signal_data) == SWITCH_STATUS_SUCCESS) {
status = SWITCH_STATUS_SUCCESS; status = SWITCH_STATUS_SUCCESS;
} }
...@@ -988,7 +988,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_signal_data(switch_c ...@@ -988,7 +988,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_signal_data(switch_c
switch_assert(session != NULL); switch_assert(session != NULL);
if (session->signal_data_queue && switch_queue_size(session->signal_data_queue)) { if (session->signal_data_queue) {
if ((status = (switch_status_t) switch_queue_trypop(session->signal_data_queue, &pop)) == SWITCH_STATUS_SUCCESS) { if ((status = (switch_status_t) switch_queue_trypop(session->signal_data_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
*signal_data = pop; *signal_data = pop;
} }
...@@ -1257,14 +1257,33 @@ SWITCH_DECLARE(switch_mutex_t *) switch_core_session_get_mutex(switch_core_sessi ...@@ -1257,14 +1257,33 @@ SWITCH_DECLARE(switch_mutex_t *) switch_core_session_get_mutex(switch_core_sessi
SWITCH_DECLARE(switch_status_t) switch_core_session_wake_session_thread(switch_core_session_t *session) SWITCH_DECLARE(switch_status_t) switch_core_session_wake_session_thread(switch_core_session_t *session)
{ {
switch_status_t status; switch_status_t status;
int tries = 0;
/* If trylock fails the signal is already awake so we needn't bother */ /* If trylock fails the signal is already awake so we needn't bother ..... or do we????*/
status = switch_mutex_trylock(session->mutex); top:
status = switch_mutex_trylock(session->mutex);
if (status == SWITCH_STATUS_SUCCESS) { if (status == SWITCH_STATUS_SUCCESS) {
switch_thread_cond_signal(session->cond); switch_thread_cond_signal(session->cond);
switch_mutex_unlock(session->mutex); switch_mutex_unlock(session->mutex);
} 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_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.
It will miss any messages in its queue because they were inserted after *it* checked its queue. (catch-22)
So, it's not asleep yet, but it's too late for us to be sure they know we want them to stay awake and check its queue again.
Now *we* need to sleep instead but just for 1ms so we can circle back and try again.
This is so rare (yet possible) to happen that we can be fairly certian it will not happen 2x in a row but we'll try 10x just in case.
*/
if (++tries < 10) {
switch_cond_next();
goto top;
}
}
} }
return status; return status;
......
...@@ -524,7 +524,16 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) ...@@ -524,7 +524,16 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
switch_channel_state_thread_lock(session->channel); switch_channel_state_thread_lock(session->channel);
switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING); switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING);
if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { 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_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_clear_flag(session->channel, CF_THREAD_SLEEPING);
switch_channel_state_thread_unlock(session->channel); switch_channel_state_thread_unlock(session->channel);
......
...@@ -851,10 +851,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_all_events(switch_core_session_ ...@@ -851,10 +851,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_all_events(switch_core_session_
x++; x++;
} }
if (x) {
switch_ivr_sleep(session, 0, SWITCH_TRUE, NULL);
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论