Почему зависает файловая 1С после успешного выполнения фонового задания с отправкой почты?

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

При сопровождении конфигураций на обычных формах (например, 1С:Управление торговлей 10.3) в файловом режиме работы разработчики нередко сталкиваются с ситуацией: регламентное или фоновое задание отрабатывает полностью, в журнале регистрации фиксируются события Фоновое задание.Успешное завершение и Сеанс.Завершение, однако сразу после этого сеанс 1С с открытой обработкой «Консоль заданий» намертво зависает и перестает отвечать на запросы операционной системы.

Проанализируем детально, почему возникает подобное поведение платформы 1С, как на это влияет объект ИнтернетПочта при пересылке больших файлов и какими способами можно полностью устранить эту проблему.

Анализ причин зависания приложения

Выясним, какие механизмы приводят к блокировке пользовательского интерфейса и системных потоков при выполнении фоновой рассылки почты в файловой базе:

  1. Зависание деструктора объекта ИнтернетПочта и дедлок сокетов. При отправке больших файлов соединение по протоколам SMTP/TLS остается активным длительное время. Если в программном коде не вызывается явный метод Отключиться(), освобождение ресурсов и закрытие сокетов выполняются платформой неявно при удалении объекта из памяти. В 32-разрядных процессах Windows сетевой стек на уровне библиотек шифрования (OpenSSL или SChannel) может удерживать сокет в состоянии TIME_WAIT, вызывая взаимную блокировку (deadlock) системного потока при завершении фонового задания.
  2. Особенности эмуляции фоновых заданий в файловом режиме. В файловой базе данных регламентные задачи запускаются в отдельных потоках внутри запущенных сеансов. Обработка «Консоль заданий» осуществляет циклический опрос состояния задач через вызов ФоновыеЗадания.ПолучитьФоновыеЗадания(). Если дочерний поток завершился логически, но заблокирован на уровне освобождения сетевых дескрипторов (handles), вызов метода получения заданий блокирует основной интерфейсный поток 1С.
  3. Влияние антивирусных систем и экранов проверки почты. Модули проверки исходящей почты (Mail Protection / SSL Filtering) перехватывают пакеты SMTP-сессии. При обработке больших вложений антивирус буферизует трафик, задерживая подтверждение закрытия TCP-сессии, из-за чего поток 1С переходит в бесконечное ожидание.
  4. Фрагментация оперативной памяти и переполнение кэша. Формирование письма с тяжелыми вложениями приводит к кодированию данных в Base64 и созданию временных файлов в каталоге %TEMP%. В условиях 32-битной архитектуры сборщик мусора 1С при выгрузке фонового потока может аварийно зацикливаться на освобождении больших непрерывных блоков памяти.

Способ 1. Корректное управление сетевым соединением и освобождение памяти

Разберем, как правильно организовать программный код отправки сообщений, чтобы гарантировать корректное закрытие TCP-сокета и своевременное освобождение оперативной памяти.

Главное правило: вызовы Подключиться() и Отключиться() должны быть строго сбалансированы и обрамлены блоком Попытка ... Исключение, а для сетевого профиля должен быть установлен достаточный таймаут ожидания.

Посмотрим на пример правильной реализации процедуры отправки почты:


Процедура ОтправитьПисьмоСФайлом(Профиль, ПочтовоеСообщение) Экспорт

    Почта = Новый ИнтернетПочта;
    
    // Задаем явный таймаут для предотвращения бесконечного ожидания ответа сервера
    Профиль.ВремяОжидания = 60;
    
    Попытка
        Почта.Подключиться(Профиль);
        Почта.Послать(ПочтовоеСообщение);
        
        // Делаем небольшую технологическую паузу для завершения обмена пакетами
        Приостановить(1);
        
        Почта.Отключиться();
    Исключение
        // Гарантированно закрываем сокет при возникновении любой ошибки
        Попытка
            Почта.Отключиться();
        Исключение
            // Игнорируем ошибку отключения, если соединение уже разорвано
        КонецПопытки;
        
        ЗаписьЖурналаРегистрации("ОтправкаПочты", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
        ВызватьИсключение;
    КонецПопытки;
    
    // Принудительно очищаем ссылки на тяжелые объекты до завершения фонового потока
    ПочтовоеСообщение = Неопределено;
    Почта = Неопределено;

КонецПроцедуры

Рассмотрим, что изменилось в коде:

  1. Установлено свойство ВремяОжидания = 60 у почтового профиля, что исключает зависание при сбоях на стороне SMTP-сервера.
  2. Метод Почта.Отключиться() вызывается явно как в штатном режиме, так и в блоке обработки исключений.
  3. Добавлена пауза Приостановить(1), позволяющая операционной системе корректно обработать закрытие TCP-соединения перед завершением потока.
  4. Выполнено явное обнуление ссылок на объекты ПочтовоеСообщение и Почта, что позволяет сборщику мусора очистить память до завершения сеанса фонового задания.

Способ 2. Очистка временных файлов после отправки

При формировании вложений платформа сохраняет промежуточные файлы в системном временном каталоге. Если они не удаляются сразу после отправки, это приводит к блокировке дескрипторов файлов процессом 1cv8.exe.

Посмотрим, как организовать корректное удаление временных вложений:


ВременныйФайл = ПолучитьИмяВременногоФайла("zip");
// ... формирование и сохранение архива во ВременныйФайл ...

ПочтовоеСообщение = Новый ИнтернетПочтовоеСообщение;
ПочтовоеСообщение.Вложения.Добавить(ВременныйФайл, "Отчет.zip");

ОтправитьПисьмоСФайлом(ПочтовыйПрофиль, ПочтовоеСообщение);

// Удаляем временный файл сразу после завершения отправки
Попытка
    УдалитьФайлы(ВременныйФайл);
Исключение
    ЗаписьЖурналаРегистрации("ОчисткаВременныхФайлов", УровеньЖурналаРегистрации.Предупреждение,,, ОписаниеОшибки());
КонецПопытки;

Способ 3. Вынос тяжелой отправки во внешний процесс

Если специфика файловой базы и особенности почтового сервера все равно приводят к дедлокам платформенного сетевого стека при отправке файлов объемом в десятки мегабайт, наиболее стабильным решением является делегирование отправки внешней системной утилите (например, curl или скрипту PowerShell).

В этом случае платформа 1С освобождается от необходимости удерживать сетевые сокеты и обрабатывать тяжелые бинарные буферы в своей памяти.

Разберем пример отправки письма через запуск скрипта PowerShell из 1С:


Процедура ОтправитьПисьмоЧерезВнешнийПроцесс(Сервер, Порт, Пользователь, Пароль, Кому, Тема, ПутьКФайлу)

    КомандаPowerShell = СтрШаблон(
        "powershell -ExecutionPolicy Bypass -Command """ +
        "$secpasswd = ConvertTo-SecureString '%1' -AsPlainText -Force; " +
        "$creds = New-Object System.Management.Automation.PSCredential ('%2', $secpasswd); " +
        "Send-MailMessage -From '%2' -To '%3' -Subject '%4' -Attachments '%5' -SmtpServer '%6' -Port %7 -UseSsl -Credential $creds;""",
        Пароль, Пользователь, Кому, Тема, ПутьКФайлу, Сервер, Формат(Порт, "ЧГ=0")
    );

    // Запускаем процесс в скрытом режиме с ожиданием завершения
    КодВозврата = 0;
    ЗапуститьПриложение(КомандаPowerShell, , Истина, КодВозврата);

    Если КодВозврата <> 0 Тогда
        ВызватьИсключение "Ошибка отправки почты через внешний процесс. Код ошибки: " + Строка(КодВозврата);
    КонецЕсли;

КонецПроцедуры

Способ 4. Настройка окружения и исключений антивируса

Проанализируем дополнительные системные настройки, которые необходимо выполнить на компьютере, где выполняются регламентные задания:

  1. Исключения антивируса: добавьте каталог информационной базы 1С, исполняемый файл 1cv8.exe и системный каталог временных файлов пользователя (%TEMP%) в белый список антивирусного монитора.
  2. Отключение перехвата SSL/TLS для почты: в настройках антивирусного ПО отключите модуль проверки защищенных почтовых протоколов (Mail Shield / SSL Inspection) либо настройте исключение для адреса вашего почтового сервера.
  3. Организация регламентных заданий: для файловых баз рекомендуется не держать постоянно открытой интерактивную «Консоль заданий», а настроить запуск отдельного служебного сеанса 1С через планировщик задач Windows с ключом /Execute <ПутьКОбработке> и последующим программным вызовом ЗавершитьРаботуСистемы(Ложь).
← На главную