diff --git a/main/dial.c b/main/dial.c index e48805ced48f60c041876121556eb2e3cf37a4fa..2766292ac5df7697621545d7486b9c24b0915c2c 100644 --- a/main/dial.c +++ b/main/dial.c @@ -58,6 +58,7 @@ struct ast_dial_channel { char *device; /*!< Device being dialed */ void *options[AST_DIAL_OPTION_MAX]; /*!< Channel specific options */ int cause; /*!< Cause code in case of failure */ + int is_running_app:1; /*!< Is this running an application? */ struct ast_channel *owner; /*!< Asterisk channel */ AST_LIST_ENTRY(ast_dial_channel) list; /*!< Linked list information */ }; @@ -135,8 +136,9 @@ static int music_disable(void *data) } /*! \brief Application execution function for 'ANSWER_EXEC' option */ -static void answer_exec_run(struct ast_channel *chan, char *app, char *args) +static void answer_exec_run(struct ast_dial *dial, struct ast_dial_channel *dial_channel, char *app, char *args) { + struct ast_channel *chan = dial_channel->owner; struct ast_app *ast_app = pbx_findapp(app); /* If the application was not found, return immediately */ @@ -146,6 +148,12 @@ static void answer_exec_run(struct ast_channel *chan, char *app, char *args) /* All is well... execute the application */ pbx_exec(chan, ast_app, args); + /* If another thread is not taking over hang up the channel */ + if (dial->thread != AST_PTHREADT_STOP) { + ast_hangup(chan); + dial_channel->owner = NULL; + } + return; } @@ -619,8 +627,11 @@ static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_chann channel->owner = NULL; } /* If ANSWER_EXEC is enabled as an option, execute application on answered channel */ - if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) - answer_exec_run(who, answer_exec->app, answer_exec->args); + if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) { + channel->is_running_app = 1; + answer_exec_run(dial, channel, answer_exec->app, answer_exec->args); + channel->is_running_app = 0; + } if (chan && dial->options[AST_DIAL_OPTION_MUSIC] && !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) { @@ -731,8 +742,16 @@ enum ast_dial_result ast_dial_join(struct ast_dial *dial) /* Stop the thread */ dial->thread = AST_PTHREADT_STOP; - /* Now we signal it with SIGURG so it will break out of it's waitfor */ - pthread_kill(thread, SIGURG); + /* If the answered channel is running an application we have to soft hangup it, can't just poke the thread */ + if (AST_LIST_FIRST(&dial->channels)->is_running_app) { + struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner; + ast_channel_lock(chan); + ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT); + ast_channel_unlock(chan); + } else { + /* Now we signal it with SIGURG so it will break out of it's waitfor */ + pthread_kill(thread, SIGURG); + } /* Finally wait for the thread to exit */ pthread_join(thread, NULL);