Commit 0515585bda for asterisk.org
commit 0515585bda3168d39344656b218bac4c109ff01b
Author: George Joseph <gjoseph@sangoma.com>
Date: Wed May 20 09:47:00 2026 -0600
Ensure channel locks aren't held while calling ast_set_variables.
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
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 90a7dc293d..f9849bda18 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -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
diff --git a/main/channel.c b/main/channel.c
index a305978e01..4de4351b70 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -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)) {
/*
diff --git a/main/pbx.c b/main/pbx.c
index f7a5ceb024..4182a63e84 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -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",
diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c
index 527803e952..85351daf5d 100644
--- a/res/ari/resource_channels.c
+++ b/res/ari/resource_channels.c
@@ -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