При выполнении обмена данными или выгрузке объектов с помощью универсальных механизмов обмена (например, подсистемы «Конвертация данных 2.x») разработчики нередко сталкиваются с аварийным завершением серверного рабочего процесса rphost. При этом в сеансе пользователя появляется сообщение об ошибке выхода из серверной процедуры или исключение вида «Переполнение стека встроенного языка на сервере», а на файлах базы или временных таблицах зависают блокировки.
Разберем детально, почему это происходит, как локализовать проблемный участок и какие настройки правил обмена позволяют устранить бесконечную рекурсию.
Причины падения процесса rphost и переполнения стека
Платформа 1С:Предприятие выделяет фиксированный объем стековой памяти для каждого потока выполнения серверного процесса. Если глубина вызовов функций встроенного языка превышает допустимый лимит, операционная система принудительно завершает поток с кодом исключения переполнения стека (0xC00000FD), что влечет за собой аварийную остановку всего рабочего процесса rphost.
Проанализируем основные источники данной проблемы при выгрузке по правилам:
Циклические ссылки в данных. Документы учета (особенно кадровые и расчетные, такие как ВозвратИзОтпускаПоУходуЗаРебенком или Отпуск) часто содержат ссылки друг на друга через реквизиты «Документ-основание», исправления или сторнирования. Выгружая первый документ, обработка инициирует выгрузку зависимого, а тот в свою очередь снова тянет исходный документ.
Автоматический выбор правила конвертации (ПКО). Если в правиле конвертации свойства (ПКС) для ссылочного реквизита не задано конкретное «облегченное» правило, платформа автоматически применяет основное ПКО по типу значения. В результате выгружается весь сложный объект целиком со всеми табличными частями и ссылками вместо обычной ссылки.
Отключение кэширования выгруженных объектов. Если в настройках выгрузки или правилах нарушен механизм запоминания уже обработанных ссылок, алгоритм многократно пытается заново выгрузить один и тот же объект, порождая лавинообразный рост стека вызовов.
Способы локализации зацикливания
Когда стандартная отладка прерывается падением сервера, выясним причину и конкретное место зацикливания следующими методами:
Тестирование в файловой базе. Выполним ту же выгрузку в файловой информационной базе под толстым клиентом. В файловом режиме платформа обычно успевает выдать стандартное диалоговое окно с полным стеком вызовов функций, где видны повторяющиеся правила обмена.
Добавление отладочного счетчика глубины. Откроем обработку выгрузки (модуль «Универсальный обмен данными в формате XML») и добавим проверку максимального уровня рекурсии в процедуру ВыгрузитьПоПравилу:
// В обработчике или модуле выгрузки
Если Параметры.СчетчикГлубины > 100 Тогда
ЗаписьЖурналаРегистрации("ОшибкаВыгрузки",
УровеньЖурналаРегистрации.Ошибка, , ,
"Превышена глубина выгрузки для объекта: " + Строка(мДок));
ВызватьИсключение "Обнаружена циклическая ссылка при выгрузке!";
КонецЕсли;
Настройка технологического журнала. На сервере 1С настроим сбор событий EXCP и PROC. Это позволит зафиксировать контекст выполнения перед аварийным падением процесса.
Методы устранения циклических ссылок в правилах обмена
Рассмотрим, как правильно настроить правила конвертации данных (КД 2.x), чтобы избежать рекурсивных вызовов:
Создание специализированных облегченных ПКО. Для реквизитов, указывающих на связанные документы (например, документ-основание), создадим отдельное правило конвертации. В нем снимем флаги выгрузки всех табличных частей и лишних реквизитов, оставив только поля поиска (номер, дата, организация). Это правило явно укажем в ПКС основного объекта.
Использование режима выгрузки только ссылки. В обработчике «Перед выгрузкой» свойства или правила можно принудительно указать выгрузку ссылки без анализа свойств самого объекта:
// Обработчик "Перед выгрузкой" для ссылочного реквизита
ТолькоПолучитьУзелСсылки = Истина;
Контроль флага запоминания выгруженных объектов. Убедимся, что для ссылочных типов включено кэширование и регистрация выгруженных объектов в служебных таблицах обмена, чтобы платформа не обрабатывала повторно ранее сериализованные ссылки.
Разрыв взаимных зависимостей. Проверим встречные ПКС: если документ «А» выгружает документ «Б», то в правиле выгрузки документа «Б» свойство, ссылающееся обратно на документ «А», должно выгружаться исключительно по ссылке без рекурсивного разбора.