Setitimer, SIGALRM и многопоточный процесс (linux, c)

Я хочу использовать setitimer() (или менее вероятно, alarm()) в многопоточном процессе в Linux 2.6+ с NPCL-совместимым libc. Какой поток получит sigalarm (SIGALRM) из ядра?

Спасибо.

2014-04 update: Как установить setitimer() в многопоточной программе, если я хочу написать служебную программу профилирования, такую ​​как gpperftools cpuprofile; но в моем инструменте я хочу поддерживать как динамически связанные программы (поэтому можно добавить мою собственную библиотеку для профилирования init) и статически связанные программы (без возможности делать ^^^^^^).

Мой текущий инструмент профилирования работает с настройкой setitimer сразу после fork() и до exec(), а также использует ptrace для получения контроля над целевой программой и для захвата SIGPROF/SIGVPROF/SIGALRM, сгенерированного с помощью setitimer. Я не знаю, как это работает с многопоточными программами.

Ответ 1

Из сигнал (7) man page:

Сигнал, направленный на процесс, может быть доставляется на любой из нитей которые в настоящее время не имеют сигнал заблокирован. Если более одного потоки имеют сигнал разблокирован, то ядро ​​выбирает произвольное нить, на которую подается сигнал.

Теперь alarm (2) man-страница говорит, что:

alarm() организует сигнал SIGALRM для доставки в процесс секунд.

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

То же самое с setitimer (2):

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

Вы можете заблокировать SIGALARM во всех ваших потоках, кроме одного, тогда вы можете быть уверены, что он будет доставлен только в этот поток. Предполагая, что вы используете pthreads, вы можете блокировать сигналы с помощью pthread_sigmask().

Ответ 2

В LKML в 2010 году была интересная тема https://lkml.org/lkml/2010/4/11/81: "setitimer vs. threads: SIGALRM вернулась в какой поток? (мастер процесса или индивидуальный ребенок)" Франтишек Рысанек (cz). Автор говорит, что setitimer используется для потоков сигналов по крайней мере в раз до Fedora 5:

... setitimer() имела гранулярность по каждой теме. Он использовал для доставки SIGALRM от таймера к конкретному потоку, который назывался setitimer().

Но в более поздних версиях Fedor изменилось поведение ( "man pthreads",... ". В потоках не используются интервальные таймеры (исправлено в ядре 2.6.12)." )

В этой теме Andi Kleen (Intel) рекомендует переключиться на "Таймеры POSIX ( timer_create)"; и в поток ML Давиде Либензи предлагает использовать timerfd (timerfd_create, timerfd_settime) для не-древних Linuxes.