C/C++ Реентрабельность функций обработки сигналов

Рейтинг: 1Ответов: 1Опубликовано: 23.03.2023

Итак, есть такое понятие, как реентрабельность функции. При обработке сигналов в linux возникают проблемы. Например, на SIGUSR1 я должен прочитать файл, и вызвать виртуальный метод, передав туда его содержимое.

void sigusr1_handler(int signum)
{
    std::string msg = read_sigmsg(get_sigmsg_filename());
    g_bootstraped->signal_handler(signum, msg); // виртуальный метод из глобального объекта
}

std::string является нереентрабельным, т.к. использует операторы new и delete, которые тоже нереентрабельные.

Я придумал три решения:

  1. Из обработчика сигнала запускать поток, в котором проделать вышеприведенные операции. Но у меня вопрос: решит ли это проблему реентрабельности? В теории должно, ведь реентрабельность - это про один и тот же поток. Но придется требовать от наследников моего класса потокобезопасности.
  2. Использовать отдельный поток, в котором через системный вызов sigwait() обрабатывать сигналы по очереди. Но тут уже не гарантируется реалтайм. Но не придется требовать от наследников моего класса потокобезопасности.
  3. Не передавать сообщения через сигналы, а использовать другой способ межпроцессного взаимодействия. Оно менее предпочтительное, в силу того, что хотелось бы единообразия, для зарезервированного моей системой сигнала, который вызывает перезагрузку процесса, получившего его.

Хотелось бы критики этих решений.

Ответы

▲ 1

Операторы new delete реентрабельные. Однако тут проблема посложнее, дело в том, что в обработчике асинхронных сигналов можно вызывать только функции из категории async-signal-safe, а не просто reentrant. Соответственно создание потоков в обработчике не допускается. не гарантируется реалтайм - он не гарантируется в любом случае.

Вариант 3 с полным отказом от сигналов выглядит предпочтительно. Чем меньше приходится иметь дело с этими атавизмами, тем лучше.