функция обработчика сигнала в многопоточной среде

В моем многопоточном приложении GUI у меня есть следующий код обработки сигналов. Я хочу улучшить этот код, чтобы он был корректным и безопасным для многопоточности, но есть некоторые вещи, которые я не совсем понимаю в обработке сигналов:

  • обрабатывается ли сигнал на уровне процесса или потока (могу ли я иметь специфичные для потока обработчики сигналов)?
  • в каком контексте потока выполняется функция signal_handler?
  • Можно ли отправить много сигналов SIGTERM за короткое время?
  • имеет ли смысл использовать мьютекс для предотвращения параллельного выполнения signal_handler?

void signal_handler(int sig)
{
switch (sig)
{
case SIGTERM:
::wxLogMessage(wxT("SIGTERM signal received ..."));
break;
case SIGINT:
::wxLogMessage(wxT("SIGINT signal received ..."));
break;
case SIGUSR1:
::wxLogMessage(wxT("SIGUSR1 signal received ..."));
break;
default:
::wxLogMessage(wxT("Unknown signal received ..."));
}

// send wxCloseEvent to main application window
::wxGetApp().GetTopWindow()->Close(true);
}

Я регистрирую обработчики сигналов в моей функции инициализации:

// register signal handlers
signal(SIGTERM, signal_handler);
signal(SIGINT,  signal_handler);
signal(SIGUSR1, signal_handler);

13

Решение

Будьте очень осторожны: как Сигнал (7) страница говорит, только очень мало функций ( «Асинхронный сигнал безопасно» из них) могут (прямо или косвенно) вызываться внутри обработчиков сигналов. Связанные с мьютексом функции, вероятно, не должны вызываться в обработчиках сигналов. Смотрите также Pthreads (7)

Вы могли бы рассмотреть возможность установки volatile sigatomic_t переменной в вашем обработчике сигналов, и время от времени проверяйте значение этого флага.
Если у вас есть атомы C ++ 11 (или C11), например, C ++ 11 станд :: атомное или C11 <stdatomic.h>, ты мог бы сделать это volatile переменная также атомная в этом смысле. Затем используйте средства атомной нагрузки, чтобы проверить это.

Документация Qt предлагает следующий трюк: создать трубы (2) самостоятельно при запуске, а затем ваш обработчик сигнала написать (2) ( write syscall указан как безопасный для асинхронного сигнала) один (или более) байт [s] для канала к тому же процессу, и ваш цикл событий GUI Опрос (2) конец чтения этой трубы.

Linux-специфические способ обработки сигналов с помощью Qt может заключаться в использовании signalfd (2) вероятно с QSocketNotifier (несмотря на название, он работает с дескрипторами файлов, которые могут только Розетки). С другими инструментами GUI вы, вероятно, также можете добавить дескриптор файла (один из signalfd или же pipe) быть опрошенным.

10

Другие решения

  • Обработчики сигналов находятся в состоянии каждого процесса, то есть все потоки в процессе совместно используют один и тот же набор установленных функций обработчика сигналов.
  • Сигнальные маски находятся в состоянии потока. Сигналы могут быть заблокированы или разблокированы для каждого потока.
  • Сигналы могут быть ориентированы на процесс или поток. Если сигнал направлен на процесс, то для его обработки выбирается произвольный поток, который в настоящее время не имеет заблокированного типа сигнала.

Простой способ обработки сигналов в многопоточном приложении — создать один поток в качестве отдельного потока обработки сигналов. Все сигналы интереса блокируются в каждом потоке; обработчики сигналов не установлены; и вызов потока обработки вызовов sigwaitinfo() в цикле, действуя на сигналы, как они получены.

Это означает, что вам не нужно беспокоиться о том, являются ли функции, которые вы хотите вызвать, асинхронному сигнал безопасно или нет, потому что сигналы не обрабатываются в обработчиках сигналов — они обрабатываются синхронно вашим выделенным потоком обработки сигналов, который может вызывать любую функцию, которая ему нравится (например, он может использовать обычные функции синхронизации pthreads для пробуждения другого потока ).

18

Этот ответ относится к потокам POSIX (pthreads).

Ссылаясь 1:

Сигналы могут обрабатываться на уровне потока, да. Если более чем один поток процесса обрабатывает сигнал и сигнал отправляется процессу, но в конкретный поток не определено, какой обработчик потока будет обрабатывать сигнал. (увидеть man pthread_kill() для деталей)

Ссылаясь 2:

Обработчик сигнала будет освобожден в контексте потока, который его установил. Это включает в себя основной поток.

Ссылаясь 3:

Если в один и тот же процесс отправлено более одного сигнала одного типа, они могут быть сконцентрированы в одном сигнале, прежде чем покинуть очередь сигналов. Могу ли я признать, что это может быть дифференцировано до уровня потока, я точно не знаю.

Ссылаясь на 4:

Если в игре задействованы общие ресурсы: да, по крайней мере для тех частей кода обработчиков, которые одновременно получают доступ к этим ресурсам. Более того, это также зависит от логики, которую вы пытаетесь реализовать.

4
По вопросам рекламы [email protected]