Справочник системных ошибок и решений

Windows Server, Active Directory, 1С:Предприятие, СУБД, Linux, Cisco, MikroTik, Asterisk.

⚠️ Важная информация Все материалы, инструкции, команды и скрипты на сайте предоставлены исключительно в ознакомительных целях. Их применение может повлиять на работу операционной системы, программного обеспечения, баз данных, сетевого оборудования и других компонентов инфраструктуры. Перед выполнением действий создайте резервную копию и по возможности протестируйте изменения в безопасной среде. Пользователь самостоятельно оценивает риски и несет ответственность за результат. При отсутствии необходимых знаний обратитесь к квалифицированному ИТ-специалисту.

DIALPLAN_MAX_LOOP_DEPTH IP-Телефония и СКУД

Asterisk: pbx_builtins.c Dialplan execution limit reached (Max loop depth exceeded)

Обновлено: 24.08.2026 · Официальная документация ↗
  • Ошибка в журнале: ERROR: pbx_builtins.c: Dialplan execution limit reached (Max loop depth exceeded).
  • Вызов мгновенно завершается при переходе между контекстами extensions.conf.
  • Абонент слышит короткие гудки или сообщение о техническом сбое.
  • В CLI фиксируется лавинообразный вывод сотен строк выполнения одного и того же extension за миллисекунды.

1. Анализ трейса выполнения диалплана

Включите расширенную детализацию диалплана:

asterisk -rvvv
core set verbose 5

Найдите циклическую конструкцию в логе выполнения (например, переход `Goto(context,exten,1)` сам на себя):

-- Executing [s@sub-check:1] Goto("PJSIP/101-0001", "sub-check,s,1")
-- Executing [s@sub-check:1] Goto("PJSIP/101-0001", "sub-check,s,1")
-- ERROR: pbx_builtins.c: Dialplan execution limit reached

2. Исправление циклических конструкций в extensions.conf

Всегда добавляйте счетчик итераций при организации циклов в диалплане:

[macro-retry-dial]
exten => s,1,Set(LOOP_CNT=0)
same => n(loop_start),Set(LOOP_CNT=$[${LOOP_CNT} + 1])
same => n,GotoIf($[${LOOP_CNT} > 3]?loop_abort)
same => n,Dial(PJSIP/100,10)
same => n,GotoIf($["${DIALSTATUS}" != "ANSWER"]?loop_start)
same => n,Return()

same => n(loop_abort),Verbose(1, [WARNING] Exceeded max retries for call)
same => n,Playback(im-sorry)
same => n,Hangup(16)

3. Проверка парных вызовов GoSub и Return

Убедитесь, что каждый переход GoSub() завершается командой Return(), предотвращая переполнение стека вызовов:

[sub-crm-lookup]
exten => s,1,NoOp(CRM Lookup)
same => n,Set(CALLERID(name)=VIP_${CALLERID(num)})
same => n,Return() ; <-- ОБЯЗАТЕЛЬНО

4. Перезагрузка диалплана

asterisk -rx "dialplan reload"
💡 Практика специалистов: Особое внимание уделите шаблонам обработки ошибок `exten => e` и `exten => i` — часто при некорректном вводе абонента они ссылаются на неверный приоритет, вызывая рекурсивный цикл.

Частые вопросы (FAQ)

Каков максимальный лимит глубины цикла в диалплане по умолчанию?

По умолчанию лимит защитного счетчика Asterisk PBX составляет 1000 итераций для предотвращения зависания процессорного ядра.

В чем разница между Goto и GoSub?

Goto выполняет безусловный прыжок на метку без сохранения точки возврата. GoSub сохраняет адрес возврата в стек, требуя обязательного вызова Return(). Пропущенный Return приводит к утечке памяти стека канала.

Как сбросить застрявший зацикленный канал?

Найдите канал через core show channels concise и завершите его: channel request hangup <Channel_Name>.

Можно ли изменить максимальный лимит глубины цикла?

Параметр жестко зашит в исходном коде main/pbx.c (константа MAX_EXPAND_DEPTH), так как 1000 шагов более чем достаточно для любой логики без рекурсивных ошибок.

Полезные материалы
Рекомендуем