Какие сигналы нельзя перехватить или игнорировать?
В Unix-системах существует два сигнала, которые невозможно перехватить, блокировать или игнорировать:
- SIGKILL (9) - Signal Kill
- SIGSTOP (19) - Signal Stop
Почему их нельзя игнорировать?
1. SIGKILL
- Назначение: Немедленное уничтожение процесса
- Особенности:
- Ядро завершает процесс без какого-либо участия самого процесса
- Не вызывает обработчиков сигналов
- Не позволяет выполнить cleanup-операции
- Гарантированное завершение даже для "зависших" процессов
Пример использования:
kill -9 <PID> # Аварийное завершение процесса
2. SIGSTOP
- Назначение: Принудительная приостановка процесса
- Особенности:
- Процесс переводится в состояние T (stopped)
- Не может быть перехвачен
- Для продолжения используется SIGCONT (18)
Пример:
kill -19 <PID> # Приостановка процесса
kill -18 <PID> # Продолжение выполнения
Технические детали реализации
-
Маска сигналов:
- Обычные сигналы можно блокировать через
sigprocmask()
- SIGKILL и SIGSTOP исключены из этой возможности
-
Обработчики:
- Попытка установить обработчик приведет к ошибке:
signal(SIGKILL, handler); // Вернет ошибку
-
Ядро Linux:
- Обрабатывает эти сигналы на уровне планировщика
- Не передает их в пространство пользователя
Практические последствия
Для разработчиков:
- Нельзя полагаться на SIGKILL для graceful shutdown
- SIGSTOP полезен для отладки, но опасен в продакшене
Для администраторов:
- SIGKILL - последнее средство для "убийства" процессов
- SIGSTOP может вызвать deadlock в IPC-механизмах
Для контейнеризации:
- Docker/Kubernetes используют SIGKILL после таймаута SIGTERM
- SIGSTOP может нарушить работу оркестратора
Как проверить неигнорируемость?
Попытка игнорировать в bash:
trap '' SIGKILL # Выдаст ошибку: "bash: trap: SIGKILL: cannot trap"
Программная проверка на C:
if (signal(SIGKILL, SIG_IGN) == SIG_ERR) {
perror("Cannot ignore SIGKILL"); // Всегда сработает
}
Альтернативы для безопасного завершения
- SIGTERM (15) - основной сигнал для graceful shutdown
- SIGQUIT (3) - создать core dump перед завершением
- SIGHUP (1) - перезапуск с перечитыванием конфигов
Пример graceful shutdown:
import signal
def graceful_exit(signum, frame):
# Cleanup operations
exit(0)
signal.signal(signal.SIGTERM, graceful_exit)
Резюмируем:
- Только SIGKILL и SIGSTOP нельзя перехватить/игнорировать
- SIGKILL - аварийное завершение без шансов на спасение
- SIGSTOP - принудительная пауза без возможности перехвата
- Все остальные сигналы можно обрабатывать или игнорировать
Профессиональный совет: Избегайте SIGKILL в скриптах автоматизации - сначала пробуйте SIGTERM с таймаутом!