История вопроса:
Perl создавался как язык для системных скриптов, поэтому управление сигналами (SIGTERM, SIGINT, SIGHUP) всегда было встроенной и мощной возможностью. Эта система позволяет перехватывать внешние события (остановка пользователя, перезапуск демона, тайм-ауты) и грамотно завершать или изменять поведение скриптов.
Проблема:
Неправильная обработка сигналов — частая причина некорректного завершения или зависания скриптов, потери данных при аварийном завершении, невозможности перезапуская процессы без потери состояния или ресурсов.
Решение:
Сигналы обрабатываются через установку обработчиков в специальном хэше %SIG. Хорошей практикой является минимализм действий внутри сигнального обработчика (например, установка флага и безопасное завершение в основном потоке). Для корректной работы в потоках и при многократных обработках сигналов используются специализированные модули (например, POSIX::sigaction).
Пример:
my $term = 0; $SIG{TERM} = sub { $term = 1; }; while (1) { last if $term; # основная работа } print "Graceful shutdown ";
Ключевые особенности:
Можно ли использовать print/IO внутри сигнального обработчика?
Ответ: Не рекомендуется — произойдет некорректная работа и возможна потеря данных! Современный стандарт — минимальный код (только установка флагов/очистка переменных).
Что произойдет, если не сбрасывать обработчик сигнала после первого срабатывания?
Ответ: Обработчик будет работать много раз, если сигнал поступает повторно. Если требуется реакция только на первое событие, обработчик должен самостоятельно сбрасывать $SIG{...} или подавать сигналы себе.
Является ли обработка сигналов потокобезопасной в Perl?
Ответ: Нет! В многопоточного Perl обработчики сигналов вызываются только в основном потоке (главном интерпретаторе); внутри потоков сигналы могут быть вообще пропущены или некорректно обработаны.
Демон-процесс при получении SIGTERM сразу вызывает close на всех файловых дескрипторах и удаляет временные файлы в обработчике — время от времени файлы не удаляются, данные теряются.
Плюсы:
Минусы:
Обработчик сигнала SIGTERM устанавливает только переменную $exit, после чего основной цикл аккуратно завершает работу, закрывает файлы и только затем освобождает ресурсы.
Плюсы:
Минусы: