diff --git a/main/autoservice.c b/main/autoservice.c index f6887f638b..12eda1a1d9 100644 --- a/main/autoservice.c +++ b/main/autoservice.c @@ -66,10 +66,24 @@ static AST_LIST_HEAD_STATIC(aslist, asent); static pthread_t asthread = AST_PTHREADT_NULL; -static void *autoservice_run(void *ign) +static void defer_frame(struct ast_channel *chan, struct ast_frame *f) { + struct ast_frame *dup_f; + struct asent *as; + + AST_LIST_LOCK(&aslist); + AST_LIST_TRAVERSE(&aslist, as, list) { + if (as->chan != chan) + continue; + if ((dup_f = ast_frdup(f))) + AST_LIST_INSERT_TAIL(&as->dtmf_frames, dup_f, frame_list); + } + AST_LIST_UNLOCK(&aslist); +} - for(;;) { +static void *autoservice_run(void *ign) +{ + for (;;) { struct ast_channel *mons[MAX_AUTOMONS]; struct ast_channel *chan; struct asent *as; @@ -91,8 +105,18 @@ static void *autoservice_run(void *ign) struct ast_frame *f = ast_read(chan); if (!f) { - /* NULL means we got a hangup*/ - ast_queue_hangup(chan); + struct ast_frame hangup_frame = { 0, }; + /* No frame means the channel has been hung up. + * A hangup frame needs to be queued here as ast_waitfor() may + * never return again for the condition to be detected outside + * of autoservice. So, we'll leave a HANGUP queued up so the + * thread in charge of this channel will know. */ + + hangup_frame.frametype = AST_FRAME_CONTROL; + hangup_frame.subclass = AST_CONTROL_HANGUP; + + defer_frame(chan, &hangup_frame); + continue; } @@ -107,18 +131,8 @@ static void *autoservice_run(void *ign) case AST_FRAME_TEXT: case AST_FRAME_IMAGE: case AST_FRAME_HTML: - { - struct ast_frame *dup_f; - - AST_LIST_LOCK(&aslist); - AST_LIST_TRAVERSE(&aslist, as, list) { - if (as->chan != chan) - continue; - if ((dup_f = ast_frdup(f))) - AST_LIST_INSERT_TAIL(&as->dtmf_frames, dup_f, frame_list); - } - AST_LIST_UNLOCK(&aslist); - } + defer_frame(chan, f); + break; /* Throw these frames away */ case AST_FRAME_VOICE: