diff options
author | Jonathan Rose <jrose@digium.com> | 2012-09-25 14:53:42 +0000 |
---|---|---|
committer | Jonathan Rose <jrose@digium.com> | 2012-09-25 14:53:42 +0000 |
commit | 39b78f6250ce890f28b59e1ae9f9c3c95cbf8176 (patch) | |
tree | 8ed77faaa30292808c3bbc7d84f6ac63fb2c3fcd /res/res_agi.c | |
parent | d9d7b1f3e3e32aa9cf0d8469607bfeaa5df6a15d (diff) |
res_agi: async_agi responsiveness improvement on datastore problems
This patch changes get_agi_cmd so that the return can be checked
to differentiate between an empty list success and something that
triggered an error. This in turn allows launch_asyncagi to detect
these errors and break free from the command processing loop so
that the async agi can be ended more cleanly
(closes issue ASTERISK-20109)
Reported by: Jeremiah Gowdy
Patches: jgowdy-7-9-2012.diff uploaded by Jeremiah Gowdy (license 6358)
(Modified by me to fix some logical issues and apply to trunk)
Review: https://reviewboard.asterisk.org/r/2117/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@373608 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_agi.c')
-rw-r--r-- | res/res_agi.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/res/res_agi.c b/res/res_agi.c index 6f7675f53..213805ed3 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -1003,10 +1003,18 @@ static const struct ast_datastore_info agi_commands_datastore_info = { .destroy = agi_destroy_commands_cb }; -static struct agi_cmd *get_agi_cmd(struct ast_channel *chan) +/*! + * \brief Retrieve the list head to the requested channel's AGI datastore + * \param chan Channel datastore is requested for + * \param cmd Pointer to the struct pointer which will reference the head of the agi command list. + * + * \retval 0 if the datastore was valid and the list head was retrieved appropriately (even if it's + * NULL and the list is empty) + * \retval -1 if the datastore could not be retrieved causing an error +*/ +static int get_agi_cmd(struct ast_channel *chan, struct agi_cmd **cmd) { struct ast_datastore *store; - struct agi_cmd *cmd; AST_LIST_HEAD(, agi_cmd) *agi_commands; ast_channel_lock(chan); @@ -1015,13 +1023,14 @@ static struct agi_cmd *get_agi_cmd(struct ast_channel *chan) if (!store) { ast_log(LOG_ERROR, "Huh? Async AGI datastore disappeared on Channel %s!\n", ast_channel_name(chan)); - return NULL; + *cmd = NULL; + return -1; } agi_commands = store->data; AST_LIST_LOCK(agi_commands); - cmd = AST_LIST_REMOVE_HEAD(agi_commands, entry); + *cmd = AST_LIST_REMOVE_HEAD(agi_commands, entry); AST_LIST_UNLOCK(agi_commands); - return cmd; + return 0; } /* channel is locked when calling this one either from the CLI or manager thread */ @@ -1322,7 +1331,16 @@ static enum agi_result launch_asyncagi(struct ast_channel *chan, char *argv[], i * Process as many commands as we can. Commands are added via * the manager or the cli threads. */ - while (!hungup && (cmd = get_agi_cmd(chan))) { + while (!hungup) { + res = get_agi_cmd(chan, &cmd); + + if (res) { + returnstatus = AGI_RESULT_FAILURE; + goto async_agi_done; + } else if (!cmd) { + break; + } + /* OK, we have a command, let's call the command handler. */ cmd_status = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0); |