Работа с асинхронными сигналами в многопоточной программе

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

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

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

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

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

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

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

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

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

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

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

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