многопоточное приложение - PullRequest
       22

многопоточное приложение

3 голосов
/ 19 августа 2010

У меня есть приложение, похожее на «отладчик», которое называется hyper-ptrace. Он запускается user_appl3, который является многопоточным с NPTL.

Основной цикл гипер-трассировки:

wait3(&status, FLAGS, &u);
// find a pid of child, which has a signal
switch (signal = WSTOPSIG(status))
{
  case SIGTRAP:
    do_some_analysis_of_the_child(pid, &status) // up to several ms
    break;
}
ptrace(PTRACE_CONT, pid); // discard signal, user_appl3 doesn't know anything 
                          //about this SIGTRAP

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

Итак, есть вопрос1 :

Если поток1 получил TRAP и отладчик перешел на do_some_analysis_of_the_child (так что отладчик не выполняет wait3 для второго потока), а чуть позже поток 2 также перешел на TRAP, что будет делать ядро ​​Linux?

По моему мнению: thread1 будет остановлен, потому что он получает сигнал и есть ожидающий отладчик. Но thread2 продолжает работать ( это? ). Когда поток 2 получает сигнал, не будет ожидающего отладчика, поэтому TRAP может быть доставлен самому потоку 2, эффективно убивая его. Я прав?

И есть второй вопрос, question2 :

Для этого случая как мне переписать основной цикл из hyper-ptrace, чтобы снизить шансы доставки сигнала в поток пользователя через отладчик? Ни аппаратное генерирование ловушек, ни пользовательское приложение не могут быть изменены. Остановка второго потока тоже не вариант.

Мне нужен анализ обоих потоков. Некоторые его части могут быть выполнены только тогда, когда поток остановлен.

Заранее спасибо!

1 Ответ

5 голосов
/ 20 августа 2010

Нет, сигнал не доставлен в приложение. Дочернее приложение остановится, когда произойдет сигнал, и ваш процесс отслеживания будет уведомлен об этом в следующий раз, когда он вызовет wait().

Вы правы - остановка трассировки применяется только к основному потоку.

Чтобы получить желаемое поведение, приостановите весь дочерний процесс (каждый поток) сразу после остановки отслеживаемого потока, отправив SIGSTOP в PID процесса, и возобновите его с SIGCONT, когда вы закончите:

wait3(&status, FLAGS, &u);

if (WIFSTOPPED(status))
    kill(pid, SIGSTOP);  /* Signal entire child process to stop */

switch (signal = WSTOPSIG(status))
{
  case SIGTRAP:
    do_some_analysis_of_the_child(pid, &status) // up to several ms
    break;
}

ptrace(PTRACE_CONT, pid, 0, 0); // discard signal, user_appl3 doesn't know anything about this SIGTRAP
kill(pid, SIGCONT);  /* Signal entire child process to resume */
...