diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/cdr.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/main/cdr.c b/main/cdr.c index 24849001c..ff7cef207 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -123,6 +123,8 @@ static const int BATCH_SCHEDULER_ONLY_DEFAULT = 0; static int batchsafeshutdown; static const int BATCH_SAFE_SHUTDOWN_DEFAULT = 1; +AST_MUTEX_DEFINE_STATIC(cdr_sched_lock); + AST_MUTEX_DEFINE_STATIC(cdr_batch_lock); /* these are used to wake up the CDR thread when there's work to do */ @@ -1360,17 +1362,24 @@ static int submit_scheduled_batch(const void *data) { ast_cdr_submit_batch(0); /* manually reschedule from this point in time */ + ast_mutex_lock(&cdr_sched_lock); cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL); + ast_mutex_unlock(&cdr_sched_lock); /* returning zero so the scheduler does not automatically reschedule */ return 0; } +/*! Do not hold the batch lock while calling this function */ static void submit_unscheduled_batch(void) { + /* Prevent two deletes from happening at the same time */ + ast_mutex_lock(&cdr_sched_lock); /* this is okay since we are not being called from within the scheduler */ AST_SCHED_DEL(sched, cdr_sched); /* schedule the submission to occur ASAP (1 ms) */ cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL); + ast_mutex_unlock(&cdr_sched_lock); + /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */ ast_mutex_lock(&cdr_pending_lock); ast_cond_signal(&cdr_pending_cond); @@ -1381,6 +1390,7 @@ void ast_cdr_detach(struct ast_cdr *cdr) { struct ast_cdr_batch_item *newtail; int curr; + int submit_batch = 0; if (!cdr) return; @@ -1427,10 +1437,14 @@ void ast_cdr_detach(struct ast_cdr *cdr) /* if we have enough stuff to post, then do it */ if (curr >= (batchsize - 1)) { - submit_unscheduled_batch(); + submit_batch = 1; } - ast_mutex_unlock(&cdr_batch_lock); + + /* Don't call submit_unscheduled_batch with the cdr_batch_lock held */ + if (submit_batch) { + submit_unscheduled_batch(); + } } static void *do_cdr(void *data) @@ -1576,7 +1590,9 @@ static void do_reload(int reload) } /* don't run the next scheduled CDR posting while reloading */ + ast_mutex_lock(&cdr_sched_lock); AST_SCHED_DEL(sched, cdr_sched); + ast_mutex_unlock(&cdr_sched_lock); for (v = ast_variable_browse(config, "general"); v; v = v->next) { if (!strcasecmp(v->name, "enable")) { @@ -1617,7 +1633,9 @@ static void do_reload(int reload) if (enabled && !batchmode) { ast_log(LOG_NOTICE, "CDR simple logging enabled.\n"); } else if (enabled && batchmode) { + ast_mutex_lock(&cdr_sched_lock); cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL); + ast_mutex_unlock(&cdr_sched_lock); ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime); } else { ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n"); @@ -1629,7 +1647,9 @@ static void do_reload(int reload) ast_cond_init(&cdr_pending_cond, NULL); if (ast_pthread_create_background(&cdr_thread, NULL, do_cdr, NULL) < 0) { ast_log(LOG_ERROR, "Unable to start CDR thread.\n"); + ast_mutex_lock(&cdr_sched_lock); AST_SCHED_DEL(sched, cdr_sched); + ast_mutex_unlock(&cdr_sched_lock); } else { ast_cli_register(&cli_submit); ast_register_atexit(ast_cdr_engine_term); |