From e7d131852c71e4c6c2e1da5971862ee02a06ede7 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 5 Mar 2026 14:45:53 +0000 Subject: [PATCH 1/4] fix deadlock in chan_pjsip_new when PJSIP_HEADER used as endpoint channel var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move endpoint channel_vars loop after ast_channel_unlock() in chan_pjsip_new() to prevent deadlock when variables invoke dialplan functions (e.g., PJSIP_HEADER) that block on PJSIP serializer tasks while the channel lock is held. Deadlock cycle with ao2_legacy (default) storage backend: 1. Thread A (chan_pjsip_new): holds channel_lock → calls pbx_builtin_setvar_helper("PJSIP_HEADER(add,...)") → dispatches to func_write_header() → ast_sip_push_task_wait_serializer() → blocks waiting for serializer to complete the task 2. Serializer thread: already processing a prior task that iterates channels → ao2_callback on channels container → acquires whole- container lock → by_name_cb tries ast_channel_lock on the channel held by Thread A → BLOCKED 3. Thread C (channel hangup): needs container lock for ao2_unlink → BLOCKED (serializer holds it) This is a classic ABBA inversion: Thread A holds channel_lock and (transitively via serializer) needs container_lock; serializer holds container_lock and needs channel_lock. The race window widened in 22.6.0 due to added channel locking in res_musiconhold.c (moh_files_alloc, local_ast_moh_start) and new CEL event publishing, increasing contention enough to trigger reliably under high call volume. Moving the loop after unlock is safe because pbx_builtin_setvar_helper() acquires its own channel lock internally. https://claude.ai/code/session_017gxrJFgjWNAVm25sYc76DP --- .../fix-pjsip-channel-creation-deadlock | 29 +++++++++++++++++++ debian/patches/series | 1 + 2 files changed, 30 insertions(+) create mode 100644 debian/patches/fix-pjsip-channel-creation-deadlock diff --git a/debian/patches/fix-pjsip-channel-creation-deadlock b/debian/patches/fix-pjsip-channel-creation-deadlock new file mode 100644 index 00000000..6af2062c --- /dev/null +++ b/debian/patches/fix-pjsip-channel-creation-deadlock @@ -0,0 +1,29 @@ +Index: asterisk-22.8.1/channels/chan_pjsip.c +=================================================================== +--- asterisk-22.8.1.orig/channels/chan_pjsip.c ++++ asterisk-22.8.1/channels/chan_pjsip.c +@@ -665,15 +665,17 @@ + ast_channel_zone_set(chan, zone); + } + +- 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 endpoint channel variables after unlock to prevent deadlock ++ * when variables invoke dialplan functions (e.g., PJSIP_HEADER) ++ * that block on serializer tasks while the channel lock is held. */ ++ 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))); ++ } ++ + set_channel_on_rtp_instance(session, ast_channel_uniqueid(chan)); + + SCOPE_EXIT_RTN_VALUE(chan); diff --git a/debian/patches/series b/debian/patches/series index 859de0f5..9c40606b 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -29,3 +29,4 @@ mix_monitor_announce_file fix-application-playback-update expose-app-queues-mutex fix-queue-deadlock +fix-pjsip-channel-creation-deadlock From 669eb857a681196d34535f8416b4cb15c7992b2f Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 5 Mar 2026 15:44:16 +0000 Subject: [PATCH 2/4] fix malformed patch: regenerate with correct tab indentation The patch was hand-written with spaces instead of tabs, causing dpkg-source to reject it as malformed. Regenerated from a real unified diff of the source file to preserve exact whitespace. https://claude.ai/code/session_017gxrJFgjWNAVm25sYc76DP --- .../fix-pjsip-channel-creation-deadlock | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/debian/patches/fix-pjsip-channel-creation-deadlock b/debian/patches/fix-pjsip-channel-creation-deadlock index 6af2062c..a96e89ee 100644 --- a/debian/patches/fix-pjsip-channel-creation-deadlock +++ b/debian/patches/fix-pjsip-channel-creation-deadlock @@ -1,29 +1,26 @@ Index: asterisk-22.8.1/channels/chan_pjsip.c =================================================================== ---- asterisk-22.8.1.orig/channels/chan_pjsip.c -+++ asterisk-22.8.1/channels/chan_pjsip.c -@@ -665,15 +665,17 @@ +--- asterisk-22.8.1.orig/channels/chan_pjsip.c 2026-03-05 15:42:57.508015668 +0000 ++++ asterisk-22.8.1/channels/chan_pjsip.c 2026-03-05 15:43:19.673013563 +0000 +@@ -665,15 +665,18 @@ ast_channel_zone_set(chan, zone); } - -- 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); - + ++ ast_channel_stage_snapshot_done(chan); ++ ast_channel_unlock(chan); ++ + /* Set endpoint channel variables after unlock to prevent deadlock + * when variables invoke dialplan functions (e.g., PJSIP_HEADER) + * that block on serializer tasks while the channel lock is held. */ -+ 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))); -+ } -+ + 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); From bf016563332ff9b3d509680585b606b0538f90a3 Mon Sep 17 00:00:00 2001 From: Charles Langlois Date: Thu, 5 Mar 2026 12:00:33 -0500 Subject: [PATCH 3/4] moved comments out of patch and into header; to minimize patch changes and avoid upstream conflicts --- debian/patches/fix-pjsip-channel-creation-deadlock | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/debian/patches/fix-pjsip-channel-creation-deadlock b/debian/patches/fix-pjsip-channel-creation-deadlock index a96e89ee..b2c7c6da 100644 --- a/debian/patches/fix-pjsip-channel-creation-deadlock +++ b/debian/patches/fix-pjsip-channel-creation-deadlock @@ -1,17 +1,18 @@ +# Set endpoint channel variables after unlock to prevent deadlock +# when variables invoke dialplan functions (e.g., PJSIP_HEADER) +# that block on serializer tasks while the channel lock is held. +# pbx_builtin_setvar_helper will acquire and release channel lock on each invocation in the loop Index: asterisk-22.8.1/channels/chan_pjsip.c =================================================================== --- asterisk-22.8.1.orig/channels/chan_pjsip.c 2026-03-05 15:42:57.508015668 +0000 +++ asterisk-22.8.1/channels/chan_pjsip.c 2026-03-05 15:43:19.673013563 +0000 -@@ -665,15 +665,18 @@ +@@ -665,15 +665,15 @@ ast_channel_zone_set(chan, zone); } + ast_channel_stage_snapshot_done(chan); + ast_channel_unlock(chan); + -+ /* Set endpoint channel variables after unlock to prevent deadlock -+ * when variables invoke dialplan functions (e.g., PJSIP_HEADER) -+ * that block on serializer tasks while the channel lock is held. */ for (var = session->endpoint->channel_vars; var; var = var->next) { char buf[512]; pbx_builtin_setvar_helper(chan, var->name, ast_get_encoded_str( From 4531095d1eb3cd95db7420d9810d0e8e6c0c3115 Mon Sep 17 00:00:00 2001 From: Charles Langlois Date: Thu, 5 Mar 2026 12:15:21 -0500 Subject: [PATCH 4/4] debian/changelog: new entry for deadlock patch --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 8608c077..9974d633 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +asterisk (8:22.8.1-1~wazo2) wazo-dev-bookworm; urgency=medium + + * Fix deadlock in chan_pjsip_new when PJSIP_HEADER used as endpoint channel var + + -- Wazo Maintainers Thu, 05 Mar 2026 10:00:00 -0500 + asterisk (8:22.8.1-1~wazo1) wazo-dev-bookworm; urgency=medium * asterisk 22.8.1