提交 9096501e authored 作者: Anthony Minessale's avatar Anthony Minessale 提交者: Sangoma Dev Box

fix race condition when hangup happends after answer indication but before the…

fix race condition when hangup happends after answer indication but before the session thread is started
上级 652d2fdf
...@@ -92,7 +92,9 @@ typedef enum { ...@@ -92,7 +92,9 @@ typedef enum {
SSF_NONE = 0, SSF_NONE = 0,
SSF_DESTROYED = (1 << 0), SSF_DESTROYED = (1 << 0),
SSF_WARN_TRANSCODE = (1 << 1), SSF_WARN_TRANSCODE = (1 << 1),
SSF_HANGUP = (1 << 2) SSF_HANGUP = (1 << 2),
SSF_THREAD_STARTED = (1 << 3),
SSF_THREAD_RUNNING = (1 << 4)
} switch_session_flag_t; } switch_session_flag_t;
...@@ -103,7 +105,6 @@ struct switch_core_session { ...@@ -103,7 +105,6 @@ struct switch_core_session {
switch_endpoint_interface_t *endpoint_interface; switch_endpoint_interface_t *endpoint_interface;
switch_size_t id; switch_size_t id;
switch_session_flag_t flags; switch_session_flag_t flags;
int thread_running;
switch_channel_t *channel; switch_channel_t *channel;
switch_io_event_hooks_t event_hooks; switch_io_event_hooks_t event_hooks;
......
...@@ -479,6 +479,7 @@ SWITCH_DECLARE(void) switch_core_session_run(_In_ switch_core_session_t *session ...@@ -479,6 +479,7 @@ SWITCH_DECLARE(void) switch_core_session_run(_In_ switch_core_session_t *session
\param session the session on which to check \param session the session on which to check
*/ */
SWITCH_DECLARE(unsigned int) switch_core_session_running(_In_ switch_core_session_t *session); SWITCH_DECLARE(unsigned int) switch_core_session_running(_In_ switch_core_session_t *session);
SWITCH_DECLARE(unsigned int) switch_core_session_started(_In_ switch_core_session_t *session);
SWITCH_DECLARE(void *) switch_core_perform_permanent_alloc(_In_ switch_size_t memory, _In_z_ const char *file, _In_z_ const char *func, _In_ int line); SWITCH_DECLARE(void *) switch_core_perform_permanent_alloc(_In_ switch_size_t memory, _In_z_ const char *file, _In_z_ const char *func, _In_ int line);
......
...@@ -106,6 +106,10 @@ static struct switch_cause_table CAUSE_CHART[] = { ...@@ -106,6 +106,10 @@ static struct switch_cause_table CAUSE_CHART[] = {
{NULL, 0} {NULL, 0}
}; };
typedef enum {
OCF_HANGUP = (1 << 0)
} opaque_channel_flag_t;
struct switch_channel { struct switch_channel {
char *name; char *name;
switch_call_direction_t direction; switch_call_direction_t direction;
...@@ -132,6 +136,7 @@ struct switch_channel { ...@@ -132,6 +136,7 @@ struct switch_channel {
int vi; int vi;
int event_count; int event_count;
int profile_index; int profile_index;
opaque_channel_flag_t opaque_flags;
}; };
SWITCH_DECLARE(const char *) switch_channel_cause2str(switch_call_cause_t cause) SWITCH_DECLARE(const char *) switch_channel_cause2str(switch_call_cause_t cause)
...@@ -2090,29 +2095,44 @@ SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel) ...@@ -2090,29 +2095,44 @@ SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel)
SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_channel_t *channel, SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_channel_t *channel,
const char *file, const char *func, int line, switch_call_cause_t hangup_cause) const char *file, const char *func, int line, switch_call_cause_t hangup_cause)
{ {
int ok = 0;
switch_assert(channel != NULL); switch_assert(channel != NULL);
/* one per customer */
switch_mutex_lock(channel->state_mutex);
if (!(channel->opaque_flags & OCF_HANGUP)) {
channel->opaque_flags |= OCF_HANGUP;
ok = 1;
}
switch_mutex_unlock(channel->state_mutex);
if (!ok) {
return channel->state;
}
switch_channel_clear_flag(channel, CF_BLOCK_STATE); switch_channel_clear_flag(channel, CF_BLOCK_STATE);
if (channel->state < CS_HANGUP) { if (channel->state < CS_HANGUP) {
switch_channel_state_t last_state; switch_channel_state_t last_state;
switch_event_t *event; switch_event_t *event;
if (hangup_cause == SWITCH_CAUSE_LOSE_RACE) {
switch_channel_set_variable(channel, "presence_call_info", NULL);
}
switch_mutex_lock(channel->state_mutex); switch_mutex_lock(channel->state_mutex);
last_state = channel->state; last_state = channel->state;
channel->state = CS_HANGUP; channel->state = CS_HANGUP;
switch_mutex_unlock(channel->state_mutex); switch_mutex_unlock(channel->state_mutex);
if (hangup_cause == SWITCH_CAUSE_LOSE_RACE) {
switch_channel_set_variable(channel, "presence_call_info", NULL);
}
channel->hangup_cause = hangup_cause; channel->hangup_cause = hangup_cause;
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Hangup %s [%s] [%s]\n", switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Hangup %s [%s] [%s]\n",
channel->name, state_names[last_state], switch_channel_cause2str(channel->hangup_cause)); channel->name, state_names[last_state], switch_channel_cause2str(channel->hangup_cause));
if (!switch_core_session_running(channel->session)) { if (!switch_core_session_running(channel->session) && !switch_core_session_started(channel->session)) {
switch_core_session_thread_launch(channel->session); switch_core_session_thread_launch(channel->session);
} }
......
...@@ -1024,7 +1024,12 @@ SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session ...@@ -1024,7 +1024,12 @@ SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session
SWITCH_DECLARE(unsigned int) switch_core_session_running(switch_core_session_t *session) SWITCH_DECLARE(unsigned int) switch_core_session_running(switch_core_session_t *session)
{ {
return session->thread_running; return switch_test_flag(session, SSF_THREAD_RUNNING) ? 1 : 0;
}
SWITCH_DECLARE(unsigned int) switch_core_session_started(switch_core_session_t *session)
{
return switch_test_flag(session, SSF_THREAD_STARTED) ? 1 : 0;
} }
SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t **session, const char *file, const char *func, int line) SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t **session, const char *file, const char *func, int line)
...@@ -1197,17 +1202,22 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_thread_launch(switch_core_se ...@@ -1197,17 +1202,22 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_thread_launch(switch_core_se
switch_mutex_lock(session->mutex); switch_mutex_lock(session->mutex);
if (!session->thread_running) { if (switch_test_flag(session, SSF_THREAD_RUNNING)) {
session->thread_running = 1; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot double-launch thread!\n");
} else if (switch_test_flag(session, SSF_THREAD_STARTED)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot launch thread again after it has already been run!\n");
} else {
switch_set_flag(session, SSF_THREAD_RUNNING);
switch_set_flag(session, SSF_THREAD_STARTED);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
if (switch_thread_create(&thread, thd_attr, switch_core_session_thread, session, session->pool) == SWITCH_STATUS_SUCCESS) { if (switch_thread_create(&thread, thd_attr, switch_core_session_thread, session, session->pool) == SWITCH_STATUS_SUCCESS) {
switch_set_flag(session, SSF_THREAD_STARTED);
status = SWITCH_STATUS_SUCCESS; status = SWITCH_STATUS_SUCCESS;
} else { } else {
session->thread_running = 0; switch_clear_flag(session, SSF_THREAD_RUNNING);
switch_clear_flag(session, SSF_THREAD_STARTED);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot create thread!\n"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot create thread!\n");
} }
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot double-launch thread!\n");
} }
switch_mutex_unlock(session->mutex); switch_mutex_unlock(session->mutex);
......
...@@ -291,7 +291,7 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) ...@@ -291,7 +291,7 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
*/ */
switch_assert(session != NULL); switch_assert(session != NULL);
session->thread_running = 1; switch_set_flag(session, SSF_THREAD_RUNNING);
endpoint_interface = session->endpoint_interface; endpoint_interface = session->endpoint_interface;
switch_assert(endpoint_interface != NULL); switch_assert(endpoint_interface != NULL);
...@@ -409,7 +409,7 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) ...@@ -409,7 +409,7 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
done: done:
switch_mutex_unlock(session->mutex); switch_mutex_unlock(session->mutex);
session->thread_running = 0; switch_clear_flag(session, SSF_THREAD_RUNNING);
} }
SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *session) SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *session)
...@@ -429,7 +429,6 @@ SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *se ...@@ -429,7 +429,6 @@ SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *se
switch_channel_clear_flag(session->channel, CF_TRANSFER); switch_channel_clear_flag(session->channel, CF_TRANSFER);
switch_channel_clear_flag(session->channel, CF_REDIRECT); switch_channel_clear_flag(session->channel, CF_REDIRECT);
session->thread_running = 1;
endpoint_interface = session->endpoint_interface; endpoint_interface = session->endpoint_interface;
switch_assert(endpoint_interface != NULL); switch_assert(endpoint_interface != NULL);
...@@ -567,7 +566,6 @@ SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t * ...@@ -567,7 +566,6 @@ SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *
switch_assert(session != NULL); switch_assert(session != NULL);
session->thread_running = 1;
endpoint_interface = session->endpoint_interface; endpoint_interface = session->endpoint_interface;
switch_assert(endpoint_interface != NULL); switch_assert(endpoint_interface != NULL);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论