Потоки POSIX и сигналы

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

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

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

76
задан Donal Fellows 5 April 2010 в 06:11
поделиться

3 ответа

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

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

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

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

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

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

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

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

46
ответ дан 24 November 2019 в 11:23
поделиться

Я нахожусь так далеко:

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

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

3
ответ дан 24 November 2019 в 11:23
поделиться

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

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

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

13
ответ дан 24 November 2019 в 11:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: