aboutsummaryrefslogtreecommitdiffstats
path: root/main
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 /main
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
Diffstat (limited to 'main')
-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);