Какие сигналы не могут быть проигнорированы?devops-54

Какие сигналы нельзя перехватить или игнорировать?

В Unix-системах существует два сигнала, которые невозможно перехватить, блокировать или игнорировать:

  1. SIGKILL (9) - Signal Kill
  2. SIGSTOP (19) - Signal Stop

Почему их нельзя игнорировать?

1. SIGKILL

  • Назначение: Немедленное уничтожение процесса
  • Особенности:
    • Ядро завершает процесс без какого-либо участия самого процесса
    • Не вызывает обработчиков сигналов
    • Не позволяет выполнить cleanup-операции
    • Гарантированное завершение даже для "зависших" процессов

Пример использования:

kill -9 <PID>  # Аварийное завершение процесса

2. SIGSTOP

  • Назначение: Принудительная приостановка процесса
  • Особенности:
    • Процесс переводится в состояние T (stopped)
    • Не может быть перехвачен
    • Для продолжения используется SIGCONT (18)

Пример:

kill -19 <PID>  # Приостановка процесса
kill -18 <PID>  # Продолжение выполнения

Технические детали реализации

  1. Маска сигналов:

    • Обычные сигналы можно блокировать через sigprocmask()
    • SIGKILL и SIGSTOP исключены из этой возможности
  2. Обработчики:

    • Попытка установить обработчик приведет к ошибке:
      signal(SIGKILL, handler);  // Вернет ошибку
      
  3. Ядро 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");  // Всегда сработает
}

Альтернативы для безопасного завершения

  1. SIGTERM (15) - основной сигнал для graceful shutdown
  2. SIGQUIT (3) - создать core dump перед завершением
  3. 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 с таймаутом!