Многопоточность, многопроцессорность с сигналами STOP и Continue
Я работаю над проектом, где мне нужно получить собственный стек Java-приложения. я могу достичь этого частично. благодаря ptrace/multiprocessing и сигналов.
в Linux обычное Java-приложение имеет минимум 14 потоков. из этих 14 меня интересует только основной поток, из которого я должен получить собственный стек. Учитывая эту цель, я запустил отдельный процесс с использованием fork(), который отслеживает собственный стек основного потока. Короче говоря, у меня есть 2 отдельных процесса: один отслеживается, а другой - мониторинг с использованием ptrace и обработки сигналов.
шаги в процессе мониторинга:
1) получить основной идентификатор потока из другого потока 14 из процесса.
2) ptrace_attach main_ID
3) ptrace_cont main_ID
непрерывный цикл начинается
{
4) kill(main_ID, SIGSTOP),
5) Наносна и проверьте статус из / proc / [pid] / stat dir
6) ptrace_peekdata для чтения стека и навигации
7) ptrace_cont main_ID
8) Наносна и проверьте статус из / proc / [pid] / stat dir
}
9) ptrace_detach main_ID
это прекрасно дает информацию о собственном стеке постоянно. но иногда я сталкиваюсь с одной проблемой.
Проблема:
когда я посылаю команду kill(main_ID, SIGSTOP) в основной поток, другие потоки процесса попадают в состояние завершения или остановки (T) и все блоки процесса. это не консистентное поведение, и весь процесс выполняется правильно. я не мог понять это поведение, поскольку я только сигнализирую основной поток, почему другие потоки затронуты этим? Может ли кто-нибудь помочь мне в анализе проблемы?
я также попытался сделать сигналы CONT и STOP во всех потоках процесса, но иногда проблема все еще возникает.
Спасибо, Сандип
1 ответ
Предполагая, что вы используете Linux, вы должны использовать tkill(2) или tgkill(2) вместо kill(2). В FreeBSD вы должны использовать системный вызов SYS_thr_kill2. В справочной странице по tkill(2):
tgkill () отправляет сигнал sig в поток с идентификатором потока tid в группе потоков tgid. (Напротив, kill(2) может использоваться только для отправки сигнала процессу (то есть группе потоков) в целом, и сигнал будет доставлен в произвольный поток внутри этого процесса.)
Не обращайте внимания на то, что tkill(2) и друзья предназначены для использования внутренней библиотекой потоков, она обычно используется отладчиками / трассировщиками для отправки сигналов определенным потокам.
Кроме того, вы должны использовать waitpid(2) (или его разновидность), чтобы дождаться, пока поток получит SIGSTOP вместо опроса /proc/[pid]/stat. Этот подход будет более эффективным и более отзывчивым.
Наконец, кажется, что вы делаете какую-то выборку из стека. Возможно, вы захотите проверить Google PerfTools, поскольку эти инструменты включают в себя сэмплер ЦП, который выполняет выборку из стека, чтобы получить оценки того, какие функции потребляют больше всего времени ЦП. Вы могли бы, возможно, повторно использовать работу, которую уже сделали эти инструменты, так как выборка из стека может быть сложно сделать надежной.