From 77ee3fe10c55430c096d91a87388e29159504e05 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 13 Mar 2013 16:10:36 -0500 Subject: [PATCH] fix a few rare race conditions that could lead to a lockup --- src/switch_core_sqldb.c | 23 ++++++++++++++++++++++- src/switch_scheduler.c | 12 ++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index cdea61ab25..1b607910c3 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1250,6 +1250,7 @@ struct switch_sql_queue_manager { int thread_running; switch_thread_cond_t *cond; switch_mutex_t *cond_mutex; + switch_mutex_t *cond2_mutex; switch_mutex_t *mutex; char *pre_trans_execute; char *post_trans_execute; @@ -1262,10 +1263,26 @@ struct switch_sql_queue_manager { static int qm_wake(switch_sql_queue_manager_t *qm) { - if (switch_mutex_trylock(qm->cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_status_t status; + int tries = 0; + + top: + + status = switch_mutex_trylock(qm->cond_mutex); + + if (status == SWITCH_STATUS_SUCCESS) { switch_thread_cond_signal(qm->cond); switch_mutex_unlock(qm->cond_mutex); return 1; + } else { + if (switch_mutex_trylock(qm->cond2_mutex) == SWITCH_STATUS_SUCCESS) { + switch_mutex_unlock(qm->cond2_mutex); + } else { + if (++tries < 10) { + switch_cond_next(); + goto top; + } + } } return 0; @@ -1407,6 +1424,7 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_stop(switch_sql_queue_m if (qm->thread) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Stopping SQL thread.\n", qm->name); + qm_wake(qm); switch_thread_join(&status, qm->thread); qm->thread = NULL; status = SWITCH_STATUS_SUCCESS; @@ -1596,6 +1614,7 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_init_name(const char *n qm->max_trans = max_trans; switch_mutex_init(&qm->cond_mutex, SWITCH_MUTEX_NESTED, qm->pool); + switch_mutex_init(&qm->cond2_mutex, SWITCH_MUTEX_NESTED, qm->pool); switch_mutex_init(&qm->mutex, SWITCH_MUTEX_NESTED, qm->pool); switch_thread_cond_create(&qm->cond, qm->pool); @@ -1850,7 +1869,9 @@ static void *SWITCH_THREAD_FUNC switch_user_sql_thread(switch_thread_t *thread, check: if ((lc = qm_ttl(qm)) == 0) { + switch_mutex_lock(qm->cond2_mutex); switch_thread_cond_wait(qm->cond, qm->cond_mutex); + switch_mutex_unlock(qm->cond2_mutex); } i = 40; diff --git a/src/switch_scheduler.c b/src/switch_scheduler.c index d6f501e453..d59a7608e3 100644 --- a/src/switch_scheduler.c +++ b/src/switch_scheduler.c @@ -37,6 +37,7 @@ struct switch_scheduler_task_container { int64_t executed; int in_thread; int destroyed; + int running; switch_scheduler_func_t func; switch_memory_pool_t *pool; uint32_t flags; @@ -124,7 +125,11 @@ static int task_thread_loop(int done) tp->in_thread = 1; switch_thread_create(&thread, thd_attr, task_own_thread, tp, tp->pool); } else { + tp->running = 1; + switch_mutex_unlock(globals.task_mutex); switch_scheduler_execute(tp); + switch_mutex_lock(globals.task_mutex); + tp->running = 0; } } } @@ -238,6 +243,13 @@ SWITCH_DECLARE(uint32_t) switch_scheduler_del_task_id(uint32_t task_id) tp->task.task_id, tp->task.group); break; } + + if (tp->running) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Attempt made to delete running task #%u (group %s)\n", + tp->task.task_id, tp->task.group); + break; + } + tp->destroyed++; if (switch_event_create(&event, SWITCH_EVENT_DEL_SCHEDULE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-ID", "%u", tp->task.task_id);