Index: main/cdr.c =================================================================== --- main/cdr.c (revision 236182) +++ main/cdr.c (working copy) @@ -63,10 +63,10 @@ char name[20]; char desc[80]; ast_cdrbe be; - AST_LIST_ENTRY(ast_cdr_beitem) list; + AST_RWLIST_ENTRY(ast_cdr_beitem) list; }; -static AST_LIST_HEAD_STATIC(be_list, ast_cdr_beitem); +static AST_RWLIST_HEAD_STATIC(be_list, ast_cdr_beitem); struct ast_cdr_batch_item { struct ast_cdr *cdr; @@ -117,12 +117,12 @@ return -1; } - AST_LIST_LOCK(&be_list); - AST_LIST_TRAVERSE(&be_list, i, list) { + AST_RWLIST_RDLOCK(&be_list); + AST_RWLIST_TRAVERSE(&be_list, i, list) { if (!strcasecmp(name, i->name)) break; } - AST_LIST_UNLOCK(&be_list); + AST_RWLIST_UNLOCK(&be_list); if (i) { ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name); @@ -136,9 +136,9 @@ ast_copy_string(i->name, name, sizeof(i->name)); ast_copy_string(i->desc, desc, sizeof(i->desc)); - AST_LIST_LOCK(&be_list); - AST_LIST_INSERT_HEAD(&be_list, i, list); - AST_LIST_UNLOCK(&be_list); + AST_RWLIST_WRLOCK(&be_list); + AST_RWLIST_INSERT_HEAD(&be_list, i, list); + AST_RWLIST_UNLOCK(&be_list); return 0; } @@ -148,18 +148,18 @@ { struct ast_cdr_beitem *i = NULL; - AST_LIST_LOCK(&be_list); - AST_LIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { + AST_RWLIST_WRLOCK(&be_list); + AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { if (!strcasecmp(name, i->name)) { - AST_LIST_REMOVE_CURRENT(&be_list, list); + AST_RWLIST_REMOVE_CURRENT(&be_list, list); if (option_verbose > 1) ast_verbose(VERBOSE_PREFIX_2 "Unregistered '%s' CDR backend\n", name); free(i); break; } } - AST_LIST_TRAVERSE_SAFE_END; - AST_LIST_UNLOCK(&be_list); + AST_RWLIST_TRAVERSE_SAFE_END; + AST_RWLIST_UNLOCK(&be_list); } int ast_cdr_isset_unanswered(void) @@ -1057,11 +1057,11 @@ ast_set_flag(cdr, AST_CDR_FLAG_POSTED); if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) continue; - AST_LIST_LOCK(&be_list); - AST_LIST_TRAVERSE(&be_list, i, list) { + AST_RWLIST_RDLOCK(&be_list); + AST_RWLIST_TRAVERSE(&be_list, i, list) { i->be(cdr); } - AST_LIST_UNLOCK(&be_list); + AST_RWLIST_UNLOCK(&be_list); } } @@ -1345,11 +1345,11 @@ ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, (batchtime != 1) ? "s" : ""); ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, (nextbatchtime != 1) ? "s" : ""); } - AST_LIST_LOCK(&be_list); - AST_LIST_TRAVERSE(&be_list, beitem, list) { + AST_RWLIST_RDLOCK(&be_list); + AST_RWLIST_TRAVERSE(&be_list, beitem, list) { ast_cli(fd, "CDR registered backend: %s\n", beitem->name); } - AST_LIST_UNLOCK(&be_list); + AST_RWLIST_UNLOCK(&be_list); } return 0; Index: main/channel.c =================================================================== --- main/channel.c (revision 236182) +++ main/channel.c (working copy) @@ -86,6 +86,10 @@ AST_THREADSTORAGE(state2str_threadbuf, state2str_threadbuf_init); #define STATE2STR_BUFSIZE 32 +#ifdef DEBUG_THREADS +AST_THREADSTORAGE(last_exceptionally, last_exceptionally_init); +#endif + /*! Default amount of time to use when emulating a digit as a begin and end * 100ms */ #define AST_DEFAULT_EMULATE_DTMF_DURATION 100 @@ -951,7 +955,25 @@ } if ((queued_voice_frames + new_voice_frames) > 96) { +#ifdef DEBUG_THREADS + time_t *last_time = ast_threadstorage_get(&last_exceptionally, sizeof(time_t)); +#endif ast_log(LOG_WARNING, "Exceptionally long voice queue length queuing to %s\n", chan->name); +#ifdef DEBUG_THREADS + if (last_time && *last_time != time(NULL)) { + FILE *f = tmpfile(); + if (f) { + char buf[1024]; + ast_cli_command(fileno(f), "core show locks"); + lseek(fileno(f), 0, SEEK_SET); + while (fgets(buf, sizeof(buf), f)) { + ast_log(LOG_WARNING, "%s", buf); + } + *last_time = time(NULL); + fclose(f); + } + } +#endif while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list))) { ast_frfree(f); } Index: main/pbx.c =================================================================== --- main/pbx.c (revision 236182) +++ main/pbx.c (working copy) @@ -5487,13 +5487,21 @@ { char *args; struct ast_flags flags = { 0 }; + int autoservice = 0; if (!ast_strlen_zero(data)) { args = ast_strdupa(data); ast_app_parse_options(resetcdr_opts, &flags, NULL, args); } + if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED) && !ast_check_hangup(chan)) { + ast_autoservice_start(chan); + autoservice = 1; + } ast_cdr_reset(chan->cdr, &flags); + if (autoservice) { + ast_autoservice_stop(chan); + } return 0; }