From: Charles Langlois Date: Thu, 16 Apr 2026 20:02:54 +0000 (-0400) Subject: chan_pjsip: Fix deadlock when endpoint set_var uses PJSIP_HEADER X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f616affc2af658fd5149374e10efcb23081339b1;p=thirdparty%2Fasterisk.git chan_pjsip: Fix deadlock when endpoint set_var uses PJSIP_HEADER When a PJSIP endpoint is configured with set_var invoking a dialplan function (e.g. PJSIP_HEADER(add,...)), chan_pjsip_new() calls pbx_builtin_setvar_helper() while holding the channel lock. For function-style variables, this dispatches to ast_func_write() which, in the case of PJSIP_HEADER, calls ast_sip_push_task_wait_serializer() -- blocking synchronously while the channel lock is held. If a concurrent operation (ARI, AMI, rtp_check_timeout) traverses the channels container via ast_channel_get_by_name(), it acquires the container lock then tries to lock individual channels in the iteration callback (by_uniqueid_cb/by_name_cb). When the serializer thread also needs the container lock, a circular dependency forms: channel_lock -> serializer_wait -> container_lock -> channel_lock This causes a complete Asterisk freeze. In the observed case, 36 threads were blocked on the container lock until res_freeze_check triggered SIGABRT after its 30-second timeout. Unlock the channel before iterating endpoint channel_vars so that dialplan functions can block without holding the channel lock. Re-lock the channel for ast_channel_stage_snapshot_done() so the batched snapshot is published under lock and captures the full channel state including the variables set during the loop. Fixes: #1872 --- diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index c2d44065fa..008f41206b 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -665,15 +665,15 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s ast_channel_zone_set(chan, zone); } + ast_channel_stage_snapshot_done(chan); + ast_channel_unlock(chan); + for (var = session->endpoint->channel_vars; var; var = var->next) { char buf[512]; pbx_builtin_setvar_helper(chan, var->name, ast_get_encoded_str( var->value, buf, sizeof(buf))); } - ast_channel_stage_snapshot_done(chan); - ast_channel_unlock(chan); - set_channel_on_rtp_instance(session, ast_channel_uniqueid(chan)); SCOPE_EXIT_RTN_VALUE(chan);