From 1982afca0dde416bef7f094292f4015c4073fc81 Mon Sep 17 00:00:00 2001 From: George Joseph Date: Wed, 20 May 2026 09:47:00 -0600 Subject: [PATCH] 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 --- include/asterisk/channel.h | 3 ++- main/channel.c | 4 ---- main/pbx.c | 4 ++-- res/ari/resource_channels.c | 2 -- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 8a31572311..4a43b5ee44 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 2d25c7a6df..afe3cacc10 100644 --- a/main/channel.c +++ b/main/channel.c @@ -6035,9 +6035,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); @@ -6102,9 +6100,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 d2419263d8..382b65235a 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -7862,10 +7862,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); @@ -8050,10 +8050,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