aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2007-11-26 21:10:29 +0000
committerfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2007-11-26 21:10:29 +0000
commit6a5b6ce0630e9e8bfa3147c97625f259376338c3 (patch)
tree80b83ab1edf702e2a89fe8ce44fc21a37368ecaa
parent43f7193ecee4c2ee7348fcf7ba1433a9670a1c1e (diff)
Fix issues with async dialing with an application executing. The application has to be terminated and control returned to the thread before hanging things up. (issue #BE-252)
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@89610 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--main/dial.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/main/dial.c b/main/dial.c
index d1432cff1..32004c055 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -61,6 +61,7 @@ struct ast_dial_channel {
const 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 */
};
@@ -123,8 +124,9 @@ static int answer_exec_disable(void *data)
}
/* 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 */
@@ -134,6 +136,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;
}
@@ -510,8 +518,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;
+ }
} else if (dial->state == AST_DIAL_RESULT_HANGUP) {
/* Hangup everything */
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
@@ -615,8 +626,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);