Почему параметр сеанса ТекущийПользователь инициализируется раньше времени при отладке?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

При исследовании механизмов запуска конфигурации, например 1С:Управление торговлей 10.3 последних редакций (включающих подсистемы БСП), разработчики нередко сталкиваются с загадочным поведением платформы: при установке точки останова в самом начале процедуры УстановкаПараметровСеанса модуля сеанса значение ПараметрыСеанса.ТекущийПользователь уже оказывается заполненным, хотя явное присвоение еще не выполнялось. Разберем детально, как устроена инициализация параметров сеанса на платформе 1С:Предприятие, как отладчик меняет естественный ход программы и как правильно локализовать момент заполнения параметров.

Механизм отложенной инициализации параметров сеанса

Проанализируем базовый принцип работы платформы с параметрами сеанса. В 1С используется модель отложенной (ленивой) инициализации. До момента первого обращения значение любого параметра сеанса является неопределенным. Обработчик события УстановкаПараметровСеанса в модуле сеанса вызывается не только один раз при старте приложения, но и каждый раз, когда код пытается прочитать значение еще не инициализированного параметра.

В процедуру передается ключевой параметр ТребуемыеПараметры:

  1. При общем запуске: параметр ТребуемыеПараметры может иметь значение Неопределено, что сигнализирует о необходимости выполнения базовой стартовой инициализации сеанса.
  2. При точечном обращении: если код обращается к конкретному параметру, платформа передает в ТребуемыеПараметры массив строк с именами тех параметров, которые запрошены в данный момент. Логика конфигурации проверяет наличие имени в массиве и инициализирует только его.

Если после завершения обработчика значение запрошенного параметра сеанса так и осталось не установленным, платформа генерирует исключение: «Попытка получения неинициализированного значения параметра сеанса».

Влияние отладчика на вызов обработчиков: ловушка окна «Табло»

Выясним причину, почему при остановке в модуле сеанса параметр ТекущийПользователь уже оказывается заполнен. Виновником такого поведения выступает сам отладчик Конфигуратора. Если выражение ПараметрыСеанса.ТекущийПользователь добавлено для отслеживания в окно «Табло», происходит следующее:

  1. Платформа останавливается на точке останова в процедуре УстановкаПараметровСеанса модуля сеанса.
  2. Среда разработки пытается вычислить все выражения, открытые в окне «Табло».
  3. Чтение выражения ПараметрыСеанса.ТекущийПользователь расценивается платформой как обращение к неинициализированному параметру сеанса.
  4. Платформа неявно инициирует вложенный вызов процедуры УстановкаПараметровСеанса, передав в ТребуемыеПараметры массив со значением "ТекущийПользователь".
  5. Отрабатывают механизмы инициализации в общих модулях (например, СтандартныеПодсистемыСервер и ПользователиСлужебный), и параметр заполняется ссылкой на текущего пользователя.
  6. В окне «Табло» мы видим уже готовое значение, а естественный пошаговый порядок отладки нарушается, создавая иллюзию, что параметр был установлен кем-то до входа в модуль сеанса.

Аналогичный скрытый эффект провоцируют:

  1. Всплывающие подсказки при случайном наведении курсора мыши на имя параметра в тексте модуля во время отладки.
  2. Выражения, оставшиеся в окне «Вычислить выражение» (Shift+F9).
  3. Просмотр объектов в окне «Локальные переменные», если свойства объекта прямо или косвенно вызывают чтение параметров сеанса.

Последовательность вызовов в типовых конфигурациях с БСП

Посмотрим на реальную последовательность событий при старте клиента (например, в УТ 10.3 с внедренными механизмами БСП), когда отладчик не вмешивается в процесс:

  1. Модуль сеанса — вызывается УстановкаПараметровСеанса() с базовым набором параметров (или ТребуемыеПараметры = Неопределено). На этом этапе ТекущийПользователь еще не заполняется.
  2. Модуль обычного приложения — управление передается в обработчик ПередНачаломРаботыСистемы().
  3. В ходе выполнения стартовых процедур система обращается к функциям получения авторизованного пользователя, например:

Функция АвторизованныйПользователь() Экспорт
    
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
    УстановитьПривилегированныйРежим(Истина);
    
    Возврат ?(ЗначениеЗаполнено(ПараметрыСеанса.ТекущийПользователь),
              ПараметрыСеанса.ТекущийПользователь,
              ПараметрыСеанса.ТекущийВнешнийПользователь);
#Иначе
    Возврат СтандартныеПодсистемыКлиентПовтИсп.ПараметрыРаботыКлиентаПриЗапуске().АвторизованныйПользователь;
#КонецЕсли
    
КонецФункции
  1. Попытка прочитать ПараметрыСеанса.ТекущийПользователь снова направляет поток выполнения в модуль сеанса — УстановкаПараметровСеанса().
  2. Модуль сеанса делегирует инициализацию общему модулю СтандартныеПодсистемыСервер.УстановкаПараметровСеанса().
  3. Вызов передается в ПользователиСлужебный.УстановкаПараметровСеанса(), где по имени пользователя информационной базы ищется элемент справочника Пользователи и окончательно присваивается параметру сеанса.

Как корректно анализировать установку параметров сеанса

Разберем практические рекомендации, которые позволят увидеть реальную картину инициализации без искажения отладочной средой:

  1. Очистка окон отладки: перед запуском отладочного сеанса полностью очистим окно «Табло» и историю диалога «Вычислить выражение».
  2. Отключение всплывающих подсказок: в конфигураторе перейдем в меню Сервис — Параметры — Модули — Редактирование и временно снимем флажок «Отображать значения переменных в подсказках при наведении курсора».
  3. Использование замера производительности: включим замер производительности до запуска сеанса («Отладка» — «Замер производительности»), выполним вход пользователя без единой точки останова, после чего остановим замер. По строке ПараметрыСеанса.ТекущийПользователь в результатах замера можно безошибочно определить точную строчку кода и модуль, где фактически произошло присвоение.
  4. Логирование через журнал регистрации: для фиксации точного времени и параметров вызова добавим временные записи в процедуру УстановкаПараметровСеанса модуля сеанса:

Если ТребуемыеПараметры = Неопределено Тогда
    СтрокаПараметров = "Все параметры";
Иначе
    СтрокаПараметров = СтрШаблон("%1", СтрСоединить(ТребуемыеПараметры, ", "));
КонецЕсли;

ЗаписьЖурналаРегистрации(
    "Инициализация параметров сеанса",
    УровеньЖурналаРегистрации.Информация,,,
    СтрокаПараметров
);

Безопасность и RLS при установке параметров сеанса

Обратим внимание на важное платформенное ограничение: при инициализации параметров сеанса поиск элементов справочников или чтение настроек обязательно должны выполняться с вызовом УстановитьПривилегированныйРежим(Истина). Если запрос к данным выполняется без привилегированного режима, а на таблицы наложены ограничения доступа (RLS), платформа внутри RLS-шаблона снова попытается прочитать параметры сеанса (в том числе текущего пользователя). Это вызовет бесконечную рекурсию, аварийный сбой и ошибку о попытке чтения неинициализированного значения.

← На главную