From b0421fc87c6f9c900635c701036e607d6402857d Mon Sep 17 00:00:00 2001 From: Alexey Khabulyak Date: Mon, 4 Aug 2025 17:48:57 +0300 Subject: [PATCH] app_dial.c: Moved channel lock to prevent deadlock It's reproducible with pbx_lua, not regular dialplan. deadlock description: 1. asterisk locks a channel 2. calls function onedigit_goto 3. calls ast_goto_if_exists funciton 4. checks ast_exists_extension -> pbx_extension_helper 5. pbx_extension_helper calls pbx_find_extension 6. Then asterisk starts autoservice in a new thread 7. autoservice run tries to lock the channel again Because our channel is locked already, autoservice can't lock. Autoservice can't lock -> autoservice stop is waiting forever. onedigit_goto waits for autoservice stop. Resolves: https://github.com/asterisk/asterisk/issues/1335 --- apps/app_dial.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/app_dial.c b/apps/app_dial.c index 93d269defb..4e583ab783 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -1808,7 +1808,10 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, if (ast_test_flag64(peerflags, OPT_DTMF_EXIT)) { const char *context; ast_channel_lock(in); - context = pbx_builtin_getvar_helper(in, "EXITCONTEXT"); + if ((context = pbx_builtin_getvar_helper(in, "EXITCONTEXT"))) { + context = ast_strdupa(context); + } + ast_channel_unlock(in); if (onedigit_goto(in, context, (char) f->subclass.integer, 1)) { ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer); *to_answer = 0; @@ -1817,14 +1820,12 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, pa->canceled = 1; publish_dial_end_event(in, out_chans, NULL, pa->status); ast_frfree(f); - ast_channel_unlock(in); if (is_cc_recall) { ast_cc_completed(in, "CC completed, but the caller used DTMF to exit"); } SCOPE_EXIT_RTN_VALUE(NULL, "%s: Caller pressed %c to end call\n", ast_channel_name(in), f->subclass.integer); } - ast_channel_unlock(in); } if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) &&