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.