Тестовые случаи в C для WIFSIGNALED, WIFSTOPPED, WIFCONTINUED - PullRequest
3 голосов
/ 25 мая 2009

Я играю с waitpid () и signal () и ищу надежные тестовые случаи для возврата WIFSIGNALED (status) = WIFSTOPPED (status) = WIFCONTINUED (status) = true, но не могу найти ни одного .. .

Не могли бы вы сказать мне, как я могу убедиться, что они возвращают true, чтобы я мог отлаживать свой код?

Кроме того, несколько советов о том, какие сигналы я должен отлавливать с помощью signal () для проверки этих макросов, было бы полезно ...

Ответы [ 4 ]

4 голосов
/ 26 мая 2009
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

#define NELEMS(x) (sizeof (x) / sizeof (x)[0])

static void testsignaled(void) {
   kill(getpid(), SIGINT);
}

static void teststopped(void) {
   kill(getpid(), SIGSTOP);
}

static void testcontinued(void) {
   kill(getpid(), SIGSTOP);
   /* Busy-work to keep us from exiting before the parent waits.
    * This is a race.
    */
   alarm(1);
   while(1) {}
}

int main(void) {
   void (*test[])(void) = {testsignaled, teststopped, testcontinued};
   pid_t pid[NELEMS(test)];
   int i, status;
   for(i = 0; i < sizeof test / sizeof test[0]; ++i) {
      pid[i] = fork();
      if(0 == pid[i]) {
         test[i]();
         return 0;
      }
   }
   /* Pause to let the child processes to do their thing.
    * This is a race.
    */
   sleep(1);
   /* Observe the stoppage of the third process and continue it. */
   wait4(pid[2], &status, WUNTRACED, 0);
   kill(pid[2], SIGCONT);
   /* Wait for the child processes. */
   for(i = 0; i < NELEMS(test); ++i) {
      wait4(pid[i], &status, WCONTINUED | WUNTRACED, 0);
      printf("%d%s%s%s\n", i, WIFCONTINUED(status) ? " CONTINUED" : "", WIFSIGNALED(status) ? " SIGNALED" : "", WIFSTOPPED(status) ? " STOPPED" : "");
   }
   return 0;
}
2 голосов
/ 26 мая 2009

Обращаться с WIFSIGNALED легко. Дочерний процесс может совершить самоубийство с помощью системного вызова kill(). Вы также можете проверить наличие дампов ядра - некоторые сигналы их создают (SIGQUIT, IIRC); некоторые сигналы не (SIGINT).

Обработка WIFSTOPPED может быть сложнее. Самый простой шаг для того, чтобы ребенок снова отправил SIGSTOP с системным вызовом kill(). На самом деле, я думаю, что это должно работать. Обратите внимание, что вы можете проверить SIGTTIN и SIGTTOU и SIGTSTOP - я считаю, что они рассчитывают на WIFSTOPPED. (Существует также вероятность того, что SIGSTOP работает только в разумных пределах при отправке отладчиком в процесс, который он выполняет через системный вызов не POSIX, ptrace().)

Обработка WIFCONTINUED - это то, что, я думаю, должен сделать родитель; после того, как вы обнаружите, что процесс был остановлен, ваш код вызова должен заставить его продолжить, отправив ему сигнал SIGCONT (снова kill()). Ребенок не может доставить это сам; это было остановлено. Опять же, я не уверен, есть ли дополнительные морщины, чтобы беспокоиться - вероятно.

1 голос
/ 26 мая 2009

Фреймворк, подобный приведенному ниже, позволит вам проверить результаты вызовов wait() и waitpid().

pid_t pid = fork();

if (pid == 0) {
    /* child */
    sleep(200);
}
else {
    /* parent */
    kill(pid, SIGSTOP);

    /* do wait(), waitpid() stuff */
}

На самом деле вам не нужно перехватывать отправляемые сигналы (используя signal() или связанную с ними функцию). signal() устанавливает обработчик, который переопределяет поведение по умолчанию для определенного сигнала - поэтому, если вы хотите проверить сигнал, завершающий ваш процесс, выберите тот, который имеет такое поведение по умолчанию - «man -s7 signal» предоставит вам подробности поведения сигнала по умолчанию .

Для упомянутых вами макросов используйте SIGSTOP для WIFSTOPPED(status), SIGCONT для WIFCONTINUED (status) и SIGINT для WIFSIGNALED(status)

Если вам нужна большая гибкость для тестирования, вы можете использовать kill (см. «man kill») для отправки сигналов вашему процессу. kill -l перечислит все сигналы, которые могут быть отправлены.

0 голосов
/ 26 мая 2009

в ваших тестах вы можете использовать fork () и посылать определенный сигнал вашим дочерним процессам? В этом сценарии ваши дочерние процессы являются тестовыми примерами?

EDIT

мой ответ о кодировании C-теста. вы вилка, получить pid вашего дочернего процесса (процесс с установленными обработчиками сигналов), вы можете отправить сигнал на него, используя kill(2). Таким образом, вы можете проверить статус выхода

...