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,38 @@ } 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]; + struct ast_channel *chan2; + 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); + if (chan->pbx) { + ast_log(LOG_WARNING, "Channel %s is at %s@%s:%d [%s(%s)] with state %s\n", + chan->name, chan->exten, chan->context, chan->priority, chan->appl, + chan->data, ast_state2str(chan->_state)); + } else if ((chan2 = ast_bridged_channel(chan))) { + ast_log(LOG_WARNING, "Bridged channel %s (slave %s) is at %s@%s:%d [%s(%s)] with state %s\n", + chan2->name, chan->name, chan2->exten, chan2->context, chan2->priority, chan2->appl, + chan2->data, ast_state2str(chan2->_state)); + if (ast_test_flag(chan2, AST_FLAG_BLOCKING)) { + pthread_kill(chan2->blocker, SIGURG); + } + } + } + } +#endif while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list))) { ast_frfree(f); } @@ -979,8 +1014,13 @@ while (new_frames--) { ioctl(chan->timingfd, DAHDI_TIMERPING, &blah); } -#endif - } else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) { +#endif + } else { + ast_log(LOG_WARNING, "Wha? Can't tell the channel that a frame is pending?!\n"); + } + /* Great; we told the channel that a frame is pending. Now, if the channel + * is blocking, kick it. */ + if (ast_test_flag(chan, AST_FLAG_BLOCKING)) { pthread_kill(chan->blocker, SIGURG); } 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/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; }