<p>Richard Mudgett has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/7456">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">CDR: Fix deadlock setting some CDR values.<br><br>Setting channel variables with the AMI Originate action caused a deadlock<br>when you set CDR(amaflags) or CDR(accountcode). This path has the channel<br>locked when the CDR function is called. The CDR function then<br>synchronously passes the job to a stasis thread. The stasis handling<br>function then attempts to lock the channel. Deadlock results.<br><br>* Avoid deadlock by making the CDR function handle setting amaflags and<br>accountcode directly on the channel rather than passing it off to the CDR<br>processing code under a stasis thread to do it.<br><br>* Made the CHANNEL function and the CDR function process amaflags the same<br>way.<br><br>* Fixed referencing the wrong message type in cdr_prop_write().<br><br>ASTERISK-27460<br><br>Change-Id: I5eacb47586bc0b8f8ff76a19bd92d1dc38b75e8f<br>---<br>M funcs/func_cdr.c<br>M funcs/func_channel.c<br>2 files changed, 90 insertions(+), 58 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/56/7456/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/funcs/func_cdr.c b/funcs/func_cdr.c<br>index 5734312..2dd9f15 100644<br>--- a/funcs/func_cdr.c<br>+++ b/funcs/func_cdr.c<br>@@ -356,7 +356,7 @@<br> <br> static void cdr_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)<br> {<br>- struct cdr_func_payload *payload = stasis_message_data(message);<br>+ struct cdr_func_payload *payload;<br> struct ast_flags flags = { 0 };<br> AST_DECLARE_APP_ARGS(args,<br> AST_APP_ARG(variable);<br>@@ -367,21 +367,17 @@<br> if (cdr_write_message_type() != stasis_message_type(message)) {<br> return;<br> }<br>-<br>+ payload = stasis_message_data(message);<br> if (!payload) {<br> return;<br> }<br>+ if (ast_strlen_zero(payload->arguments)<br>+ || !payload->value) {<br>+ /* Sanity check. cdr_write() could never send these bad messages */<br>+ ast_assert(0);<br>+ return;<br>+ }<br> <br>- if (ast_strlen_zero(payload->arguments)) {<br>- ast_log(AST_LOG_WARNING, "%s requires a variable (%s(variable)=value)\n)",<br>- payload->cmd, payload->cmd);<br>- return;<br>- }<br>- if (!payload->value) {<br>- ast_log(AST_LOG_WARNING, "%s requires a value (%s(variable)=value)\n)",<br>- payload->cmd, payload->cmd);<br>- return;<br>- }<br> parse = ast_strdupa(payload->arguments);<br> AST_STANDARD_APP_ARGS(args, parse);<br> <br>@@ -389,32 +385,16 @@<br> ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);<br> }<br> <br>- if (!strcasecmp(args.variable, "accountcode")) {<br>- ast_log(AST_LOG_WARNING, "Using the CDR function to set 'accountcode' is deprecated. Please use the CHANNEL function instead.\n");<br>- ast_channel_lock(payload->chan);<br>- ast_channel_accountcode_set(payload->chan, payload->value);<br>- ast_channel_unlock(payload->chan);<br>- } else if (!strcasecmp(args.variable, "peeraccount")) {<br>- ast_log(AST_LOG_WARNING, "The 'peeraccount' setting is not supported. Please set the 'accountcode' on the appropriate channel using the CHANNEL function.\n");<br>- } else if (!strcasecmp(args.variable, "userfield")) {<br>+ /* These are already handled by cdr_write() */<br>+ ast_assert(strcasecmp(args.variable, "accountcode")<br>+ && strcasecmp(args.variable, "peeraccount")<br>+ && strcasecmp(args.variable, "amaflags"));<br>+<br>+ if (!strcasecmp(args.variable, "userfield")) {<br> ast_cdr_setuserfield(ast_channel_name(payload->chan), payload->value);<br>- } else if (!strcasecmp(args.variable, "amaflags")) {<br>- ast_log(AST_LOG_WARNING, "Using the CDR function to set 'amaflags' is deprecated. Please use the CHANNEL function instead.\n");<br>- if (isdigit(*payload->value)) {<br>- int amaflags;<br>- sscanf(payload->value, "%30d", &amaflags);<br>- ast_channel_lock(payload->chan);<br>- ast_channel_amaflags_set(payload->chan, amaflags);<br>- ast_channel_unlock(payload->chan);<br>- } else {<br>- ast_channel_lock(payload->chan);<br>- ast_channel_amaflags_set(payload->chan, ast_channel_string2amaflag(payload->value));<br>- ast_channel_unlock(payload->chan);<br>- }<br> } else {<br> ast_cdr_setvar(ast_channel_name(payload->chan), args.variable, payload->value);<br> }<br>- return;<br> }<br> <br> static void cdr_prop_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)<br>@@ -523,27 +503,70 @@<br> return 0;<br> }<br> <br>-static int cdr_write(struct ast_channel *chan, const char *cmd, char *parse,<br>- const char *value)<br>+static int cdr_write(struct ast_channel *chan, const char *cmd, char *arguments,<br>+ const char *value)<br> {<br>- RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);<br>- RAII_VAR(struct cdr_func_payload *, payload, NULL, ao2_cleanup);<br>- RAII_VAR(struct stasis_message_router *, router,<br>- ast_cdr_message_router(), ao2_cleanup);<br>+ struct stasis_message *message;<br>+ struct cdr_func_payload *payload;<br>+ struct stasis_message_router *router;<br>+ AST_DECLARE_APP_ARGS(args,<br>+ AST_APP_ARG(variable);<br>+ AST_APP_ARG(options);<br>+ );<br>+ char *parse;<br> <br> if (!chan) {<br> ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);<br> return -1;<br> }<br>-<br>- if (!router) {<br>- ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",<br>- ast_channel_name(chan));<br>+ if (ast_strlen_zero(arguments)) {<br>+ ast_log(LOG_WARNING, "%s requires a variable (%s(variable)=value)\n)",<br>+ cmd, cmd);<br>+ return -1;<br>+ }<br>+ if (!value) {<br>+ ast_log(LOG_WARNING, "%s requires a value (%s(variable)=value)\n)",<br>+ cmd, cmd);<br> return -1;<br> }<br> <br>+ parse = ast_strdupa(arguments);<br>+ AST_STANDARD_APP_ARGS(args, parse);<br>+<br>+ /* These CDR variables are no longer supported or set directly on the channel */<br>+ if (!strcasecmp(args.variable, "accountcode")) {<br>+ ast_log(LOG_WARNING, "Using the %s function to set 'accountcode' is deprecated. Please use the CHANNEL function instead.\n",<br>+ cmd);<br>+ ast_channel_lock(chan);<br>+ ast_channel_accountcode_set(chan, value);<br>+ ast_channel_unlock(chan);<br>+ return 0;<br>+ }<br>+ if (!strcasecmp(args.variable, "amaflags")) {<br>+ int amaflags;<br>+<br>+ ast_log(LOG_WARNING, "Using the %s function to set 'amaflags' is deprecated. Please use the CHANNEL function instead.\n",<br>+ cmd);<br>+ if (isdigit(*value)) {<br>+ if (sscanf(value, "%30d", &amaflags) != 1) {<br>+ amaflags = AST_AMA_NONE;<br>+ }<br>+ } else {<br>+ amaflags = ast_channel_string2amaflag(value);<br>+ }<br>+ ast_channel_lock(chan);<br>+ ast_channel_amaflags_set(chan, amaflags);<br>+ ast_channel_unlock(chan);<br>+ return 0;<br>+ }<br>+ if (!strcasecmp(args.variable, "peeraccount")) {<br>+ ast_log(LOG_WARNING, "The 'peeraccount' setting is not supported. Please set the 'accountcode' on the appropriate channel using the CHANNEL function.\n");<br>+ return 0;<br>+ }<br>+<br>+ /* The remaining CDR variables are handled by CDR processing code */<br> if (!cdr_write_message_type()) {<br>- ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",<br>+ ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",<br> ast_channel_name(chan));<br> return -1;<br> }<br>@@ -554,16 +577,26 @@<br> }<br> payload->chan = chan;<br> payload->cmd = cmd;<br>- payload->arguments = parse;<br>+ payload->arguments = arguments;<br> payload->value = value;<br> <br> message = stasis_message_create(cdr_write_message_type(), payload);<br>+ ao2_ref(payload, -1);<br> if (!message) {<br>- ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",<br>+ ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",<br> ast_channel_name(chan));<br> return -1;<br> }<br>+ router = ast_cdr_message_router();<br>+ if (!router) {<br>+ ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",<br>+ ast_channel_name(chan));<br>+ ao2_ref(message, -1);<br>+ return -1;<br>+ }<br> stasis_message_router_publish_sync(router, message);<br>+ ao2_ref(router, -1);<br>+ ao2_ref(message, -1);<br> <br> return 0;<br> }<br>@@ -586,7 +619,7 @@<br> return -1;<br> }<br> <br>- if (!cdr_write_message_type()) {<br>+ if (!cdr_prop_write_message_type()) {<br> ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",<br> ast_channel_name(chan));<br> return -1;<br>diff --git a/funcs/func_channel.c b/funcs/func_channel.c<br>index eb3cedd..b72cb14 100644<br>--- a/funcs/func_channel.c<br>+++ b/funcs/func_channel.c<br>@@ -495,18 +495,17 @@<br> ast_bridge_set_after_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);<br> }<br> } else if (!strcasecmp(data, "amaflags")) {<br>- ast_channel_lock(chan);<br>+ int amaflags;<br>+<br> if (isdigit(*value)) {<br>- int amaflags;<br>- sscanf(value, "%30d", &amaflags);<br>- ast_channel_amaflags_set(chan, amaflags);<br>- } else if (!strcasecmp(value,"OMIT")){<br>- ast_channel_amaflags_set(chan, 1);<br>- } else if (!strcasecmp(value,"BILLING")){<br>- ast_channel_amaflags_set(chan, 2);<br>- } else if (!strcasecmp(value,"DOCUMENTATION")){<br>- ast_channel_amaflags_set(chan, 3);<br>+ if (sscanf(value, "%30d", &amaflags) != 1) {<br>+ amaflags = AST_AMA_NONE;<br>+ }<br>+ } else {<br>+ amaflags = ast_channel_string2amaflag(value);<br> }<br>+ ast_channel_lock(chan);<br>+ ast_channel_amaflags_set(chan, amaflags);<br> ast_channel_unlock(chan);<br> } else if (!strcasecmp(data, "peeraccount"))<br> locked_string_field_set(chan, peeraccount, value);<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7456">change 7456</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/7456"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 15 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I5eacb47586bc0b8f8ff76a19bd92d1dc38b75e8f </div>
<div style="display:none"> Gerrit-Change-Number: 7456 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Richard Mudgett <rmudgett@digium.com> </div>