POSIX темы и сигналы - PullRequest
       11

POSIX темы и сигналы

75 голосов
/ 04 апреля 2010

Я пытался понять тонкости взаимодействия потоков POSIX и сигналов POSIX. В частности, меня интересует:

  • Каков наилучший способ контролировать, в какой поток доставляется сигнал (если он изначально не является фатальным)?
  • Каков наилучший способ сообщить другому потоку (который на самом деле может быть занят), что сигнал поступил? (Я уже знаю, что это плохая идея - использовать переменные условия pthread из обработчика сигнала.)
  • Как я могу безопасно обрабатывать передачу информации о том, что сигнал поступил в другие потоки? Это должно произойти в обработчике сигнала? (Я вообще не хочу убивать другие потоки; мне нужен более тонкий подход.)

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

Ответы [ 4 ]

45 голосов
/ 23 апреля 2010
  • Какой лучший способ контролировать, какой поток сигнал доставляется на?

Как указано @ zoli2k, хорошая методика - однозначное назначение отдельного потока для обработки всех сигналов, которые вы хотите обработать (или набор потоков, каждый с определенными обязанностями в отношении сигналов), - хороший метод.

  • Каков наилучший способ сообщить другому потоку (который на самом деле может быть занят) что сигнал поступил? [...]
  • Как я могу безопасно обрабатывать передачу информации о том, что сигнал произошел в другие темы? Это должно произойти в обработчике сигнала?

Я не скажу «лучший», но вот моя рекомендация:

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

Самый простой способ сделать это - заставить поток принимать сигналы в цикле, используя sigwaitinfo или sigtimedwait. Затем поток каким-то образом преобразует сигналы, возможно, транслируя pthread_cond_t, пробуждая другие потоки с большим количеством операций ввода-вывода, помещая команду в очередь, ориентированную на применение в потоке-безопасной очереди, что угодно.

В качестве альтернативы, специальный поток может позволять доставлять сигналы обработчику сигналов, снимая маску для доставки только тогда, когда он готов к обработке сигналов. (Однако доставка сигнала через обработчики имеет тенденцию быть более подверженной ошибкам, чем прием сигнала через семейство sigwait.) В этом случае обработчик сигнала приемника выполняет простое и безопасное для асинхронного сигнала действие: установка флагов sig_atomic_t, вызов sigaddset(&signals_i_have_seen_recently, latest_sig), write () байта для неблокирующей self-pipe и т. д. Затем, возвращаясь в свой замаскированный основной цикл, поток сообщает о получении сигнала другим потокам, как указано выше. .

( ОБНОВЛЕНО @caf справедливо указывает, что sigwait подходы превосходят.)

13 голосов
/ 04 апреля 2010

В соответствии со стандартом POSIX все потоки должны появляться с одинаковым PID в системе, и с помощью pthread_sigmask() вы можете определить маску блокировки сигнала для каждого потока.

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

В некоторых старых системах из-за отсутствия надлежащей поддержки ядра запущенные потоки могут иметь PID, отличный от родительскогоPID потока.См. FAQ для обработки сигналов с linuxThreads в Linux 2.4 .

4 голосов
/ 15 марта 2013

ИМХО, сигналы Unix V и потоки posix плохо смешиваются. Unix V 1970. POSIX 1980;)

Существуют точки отмены, и если вы разрешите сигналы и потоки в одном приложении, вы в конечном итоге получите циклы вокруг каждого вызова, что может неожиданно вернуть EINTR.

То, что я делал в (нескольких) случаях, когда мне приходилось программировать многопоточность в Linux или QNX, было для маскировки всех сигналов для всех (кроме одного) потоков.

Когда поступает сигнал Unix V, процесс переключает стек (это было столько параллелизма в Unix V, сколько вы могли получить в процессе).

Как подсказывают другие посты, теперь можно сказать Системе, какой поток posix должен стать жертвой переключения стека.

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

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

3 голосов
/ 08 апреля 2010

Где я сейчас нахожусь:

  • Сигналы бывают разных основных классов, некоторые из которых, как правило, просто все равно должны уничтожать процесс (SIGILL), а некоторые из них никогда не нуждаются в каких-либо действиях (SIGIO; в любом случае проще просто сделать правильный асинхронный ввод-вывод). Эти два класса не нуждаются в действиях.
  • С некоторыми сигналами не нужно разбираться немедленно; подобных SIGWINCH можно ставить в очередь до тех пор, пока он не станет удобным (как событие из X11).
  • Сложными являются те, где вы хотите ответить на них, прерывая то, что вы делаете, но не вдаваясь в степень уничтожения потока. В частности, SIGINT в интерактивном режиме должна оставлять вещи отзывчивыми.

Мне все еще нужно разобраться с signal против sigaction, pselect, sigwait, sigaltstack и целой кучей других кусочков POSIX (и не POSIX) API.

...