Я пытался понять запутанность того, как взаимодействуют потоки POSIX и сигналы POSIX. В частности, я интересуюсь:
Для ссылки о том, почему я хочу это, я исследую, как преобразовать пакет TclX, чтобы поддерживать потоки, или разделить его и по крайней мере заставить некоторые полезные части поддерживать потоки. Сигналы являются одной из тех частей, которая особенно интересна.
- Как лучше всего контролировать, в какой поток доставляется сигнал?
Как указано в @ zoli2k, явное назначение одного потока для обработки всех сигналов, которые вы хотите обработать (или набора потоков, каждый из которых имеет определенные обязанности по сигналу), является хорошей техникой.
- Как лучше всего сообщить другому потоку (который на самом деле может быть занят) , что сигнал прибыл? [...]
- Как я могу безопасно обрабатывать передачу информации, которую имеет сигнал произошло с другими потоками? Должно ли это происходить в обработчике сигналов?
Я не буду говорить «лучше всего», но вот моя рекомендация:
Заблокируйте все желаемые сигналы в main
, чтобы все потоки унаследовали это сигнальная маска. Затем модифицируйте поток приема специальных сигналов как управляемый сигналами цикл событий, отправляя вновь поступившие сигналы как некоторую другую внутрипотоковую связь .
Самый простой способ сделать это - заставить поток принимать сигналы в цикле с использованием sigwaitinfo
или sigtimedwait
. Затем поток каким-то образом преобразует сигналы, возможно, транслируя pthread_cond_t
, пробуждая другие потоки с большим количеством операций ввода-вывода, помещая команду в очередь, ориентированную на конкретное приложение, потокобезопасную, что угодно.
В качестве альтернативы, специальный поток может разрешить доставку сигналов обработчику сигналов, демаскируя их для доставки только тогда, когда они готовы обработать сигналы. (Однако доставка сигнала через обработчики более подвержена ошибкам, чем прием сигнала через семейство sigwait
.) В этом случае обработчик сигнала получателя выполняет простое и безопасное для асинхронного сигнала действие: установка флаги sig_atomic_t
, вызов sigaddset (& signal_i_have_seen_recently, latest_sig)
, запись
() байта в неблокирующий самотрубок и т. Д. Затем, вернувшись в свой замаскированный основной цикл, поток сообщает о получении сигнала другим потокам, как указано выше.
( ОБНОВЛЕНО @caf справедливо указывает, что подходы sigwait
лучше.)
Я нахожусь так далеко:
Мне еще нужно отсортировать сигнал
против sigaction
, pselect
, sigwait
, sigaltstack
и множество других частей API POSIX (и не POSIX).
Согласно стандарту POSIX все потоки должны появляться в системе с одним и тем же PID, а с помощью pthread_sigmask ()
вы можете определить сигнал блокирующая маска для каждого потока.
Поскольку разрешено определять только один обработчик сигналов для каждого PID, я предпочитаю обрабатывать все сигналы в одном потоке и отправлять pthread_cancel ()
, если работающий поток необходимо отменить. Это предпочтительный способ против pthread_kill ()
, поскольку он позволяет определять функции очистки для потоков.
В некоторых старых системах из-за отсутствия надлежащей поддержки ядра запущенные потоки могут иметь PID, отличный от PID родительского потока. См. FAQ по обработке сигналов с linuxThreads в Linux 2.4 .