]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Ensure channel locks aren't held while calling ast_set_variables.
authorGeorge Joseph <gjoseph@sangoma.com>
Wed, 20 May 2026 15:47:00 +0000 (09:47 -0600)
committergithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Mon, 1 Jun 2026 15:30:20 +0000 (15:30 +0000)
If the channel is locked when calling ast_set_variables and any of the
variables contained dialplan functions, there's a possiblilty of a deadlock.
To prevent this, either the explicit locks were removed or the call to
ast_set_variables moved out of the lock scope.  A warning to not hold
channel locks is also added to the documentation for ast_set_variables.

Resolves: #1936

include/asterisk/channel.h
main/channel.c
main/pbx.c
res/ari/resource_channels.c

index 90a7dc293d64036d820fa0bcd5f089c643f9e792..f9849bda18d2ce061c5f545f14f313b3a0343460 100644 (file)
@@ -2749,7 +2749,8 @@ void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_
  * \param chan the channel
  * \param vars a linked list of variables
  *
- * \pre chan is locked
+ * \warning The channel must not be locked if there's a possibility that
+ * a dialplan function would be invoked.
  *
  * \details
  * Variable names can be for a regular channel variable or a dialplan function
index a305978e014299739a3c75483e1203b68e9129c7..4de4351b707ca2dd45820ba3c17768b454525d48 100644 (file)
@@ -5952,9 +5952,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
        /* Copy/inherit important information into new channel */
        if (oh) {
                if (oh->vars) {
-                       ast_channel_lock(new_chan);
                        ast_set_variables(new_chan, oh->vars);
-                       ast_channel_unlock(new_chan);
                }
                if (oh->parent_channel) {
                        call_forward_inherit(new_chan, oh->parent_channel, orig);
@@ -6019,9 +6017,7 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
 
        if (oh) {
                if (oh->vars) {
-                       ast_channel_lock(chan);
                        ast_set_variables(chan, oh->vars);
-                       ast_channel_unlock(chan);
                }
                if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name)) {
                        /*
index f7a5ceb024f50d63f5fa41db2844d33855440366..4182a63e84ef596366d39dcf77d4171b8ad7915a 100644 (file)
@@ -7817,10 +7817,10 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap,
                return -1;
        }
 
-       ast_channel_lock(dialed);
        if (vars) {
                ast_set_variables(dialed, vars);
        }
+       ast_channel_lock(dialed);
        if (!ast_strlen_zero(account)) {
                ast_channel_stage_snapshot(dialed);
                ast_channel_accountcode_set(dialed, account);
@@ -8005,10 +8005,10 @@ int ast_pbx_outgoing_exten_predial(const char *type, struct ast_format_cap *cap,
                if (failed) {
                        char failed_reason[12];
 
-                       ast_set_variables(failed, vars);
                        snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
                        pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
                        ast_channel_unlock(failed);
+                       ast_set_variables(failed, vars);
 
                        if (ast_pbx_run(failed)) {
                                ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n",
index 527803e952db4d7f6c15ab98ab00ce5888e04f87..85351daf5dda4d82a63ae25391df8ecc0866f1fe 100644 (file)
@@ -1372,7 +1372,6 @@ static struct ast_channel *ari_channels_handle_originate_with_id(const char *arg
                ast_channel_set_connected_line(chan, &connected, NULL);
        }
 
-       ast_channel_lock(chan);
        if (variables) {
                ast_set_variables(chan, variables);
        }
@@ -1392,7 +1391,6 @@ static struct ast_channel *ari_channels_handle_originate_with_id(const char *arg
        }
 
        snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
-       ast_channel_unlock(chan);
 
        /* Before starting the async dial bump the ref in case the dial quickly goes away and takes
         * the reference with it