Работа с асинхронными сигналами в многопоточной программе - PullRequest
12 голосов
/ 03 июня 2011

В книге Linux Programming Interface Book упоминается метод работы с асинхронными сигналами в многопоточной программе:

  • Все потоки блокируют все асинхронные сигналы, которые может получить процесс.Самый простой способ сделать это - заблокировать сигналы в главном потоке перед созданием любого другого потока.Каждый впоследствии созданный поток наследует копию маски сигналов основного потока.
  • создает отдельный выделенный поток, который принимает входящие сигналы, используя sigwaitinfo(), sigtimedwait() или sigwait().

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

Теперь вопросы:

  1. , когда ядро ​​хочет доставлять сигналы, оно выбирает один изпотоки внутри процесса произвольны.откуда он может знать, что он доставляет сигнал в выделенный поток?
  2. pthread API - это функции, не являющиеся безопасными для aync.так как мы можем использовать их внутри обработчика сигнала?

Ответы [ 3 ]

8 голосов
/ 03 июня 2011

Когда ядро ​​подает сигнал, ориентированный на процесс, оно выбирает один из потоков , для которого сигнал не заблокирован . Это означает, что он никогда не выбирает ни один из потоков, кроме потока обработки сигнала (который действует так, как если бы сигнал был разблокирован, пока он заблокирован в sigwaitinfo() или аналогичном). Другими словами: ядро ​​знает, куда доставить сигнал, потому что вы организовали такие вещи, что поток обработки сигналов является единственным потоком, которому когда-либо разрешено доставлять сигнал.

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

3 голосов
/ 03 июня 2011

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

Чтобы ответить на ваши вопросы:

  1. Прочитайте справочную страницу для sigwait () (и / или sigwaitinfo () ). Когда ядро ​​хочет отправить вашему процессу сигнал, но все потоки заблокировали сигнал, сигнал попадает в «очередь». Он остается в очереди, пока (а) какой-либо поток не разблокирует сигнал; или (b) некоторые потоки вызывают sigwait () или sigwaitinfo () для сигнала. Предложение здесь состоит в том, чтобы посвятить нить этому последнему.

  2. Идея состоит в том, что вы никогда не запускаете никаких обработчиков сигналов, потому что никакой поток никогда не разблокирует сигнал. Вместо этого один поток ожидает сигнал с помощью sigwait (), а затем обрабатывает сигнал. Все это происходит вне контекста обработки сигналов, что является прелестью предложения.

0 голосов
/ 12 августа 2014

Вы можете косвенно вызывать API-интерфейсы pthread из обработчика сигнала, используя другой механизм. В главном потоке создайте сокет домена Unix, который слушает определенные команды. Обработчик сигнала может иметь код для подключения к сокету и отправки команд в основной поток для вызова API pthread, который вы хотите вызвать.

...