Как правильно обрабатывать сигналы, чтобы профилировщик процессора gperftools все еще работал?

Я хочу профилировать мою программу-демон, которая приостанавливает основной поток:

sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGTERM);
sigaddset(&signal_mask, SIGINT);

int sig;
sigwait(&signal_mask, &sig);

Все остальные потоки просто блокируют все сигналы.
Насколько я знаю, профилировщик использует SIGPROF сигнал для его операций. Если я начну профилирование с таким кодом, выходной файл .prof будет пустым:

env CPUPROFILE = daemon.prof ./daemon

Как правильно обрабатывать сигналы в основном потоке и других потоках, чтобы включить профилирование? Или может проблема в другом?

5

Решение

Все остальные потоки просто блокируют все сигналы.

Вам просто нужно разблокировать SIGPROF во всех темах (или в тех, которые вы хотите профилировать). Мы просто решали точно такую ​​же проблему в многопоточном демоне.

1

Другие решения

Мне нужно увидеть больше вашего кода, но ваше заявление о том, что «все остальные потоки просто блокируют все сигналы» вызывает … сигналы.

Вы должны помнить, что большинство системных вызовов были созданы до того, как существовала концепция потоков. Обработка сигналов является одним из них. Таким образом, когда вы блокируете сигнал в ЛЮБОМ потоке, он, вероятно, блокируется для ВСЕХ потоков.

На самом деле, проверьте man-страницу signal (2):

The effects of signal() in a multithreaded process are unspecified.

Да, это печально, но это цена, которую вы должны заплатить за использование статистического профилировщика выборки с низкими издержками. И обойти это очень просто: просто удалите SIGPROF (или SIGALRM, если вы используете режим REAL) из своего набора маски сигнала, и все будет в порядке.

И вообще, если только вы не обязаны это делать, вы не должны выполнять маскирование сигналов на уровне процесса ни в чем, кроме основного потока … где «main» не обязательно означает поток, в котором выполняется MAIN (), но скорее, нить, которую вы считаете «боссом» всех остальных, по причинам, которые вы уже слишком ясно прояснили. 🙂

Вы также можете попробовать использовать Оболочка сигма-библиотеки библиотеки pthread pthread_sigmask, но мне неясно, насколько хорошо он работает в таких ситуациях, как дочерний поток, УДАЛЯЮЩИЙ запись из сигма-маски (pthreads наследуют сигма-маску pthread своего родителя).

0

По вопросам рекламы [email protected]