Можно ли заблокировать сигналы в Linux?

«Можно ли заблокировать сигналы в Linux?» — вопрос из категории Linux и ОС, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, в Linux можно временно блокировать доставку сигналов процессу или потоку. Это делается с помощью функций управления сигнальной маской.

Основные функции:

  • sigprocmask() — для однопоточных процессов.
  • pthread_sigmask() — для управления сигналами в отдельных потоках многопоточного приложения.

Пример блокировки SIGINT в процессе:

#include <signal.h>

int main() {
    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGINT);  // Добавляем SIGINT в набор
    // Блокируем сигналы из набора
    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
        perror("sigprocmask");
        return 1;
    }
    // Критическая секция, где SIGINT не будет прерывать выполнение
    // ...
    return 0;
}

Важные детали:

  1. Неблокируемые сигналы: SIGKILL и SIGSTOP заблокировать невозможно. Ядро всегда их доставит.
  2. Блокировка vs. Игнорирование: Блокировка (SIG_BLOCK) временно откладывает доставку сигнала (сигнал ставится в очередь ожидания), в то время как игнорирование (signal(SIGINT, SIG_IGN)) приводит к его безвозвратной потере.
  3. Проверка ожидающих сигналов: Функция sigpending() позволяет получить набор сигналов, ожидающих доставки.
  4. Разблокировка: Для возобновления получения сигналов используется SIG_UNBLOCK.
    sigprocmask(SIG_UNBLOCK, &mask, NULL);
  5. Многопоточность: В многопоточных программах каждый поток имеет свою сигнальную маску. pthread_sigmask() используется внутри потока для управления его собственной маской.