Тестовые примеры на языке C для WIFSIGNALED, WIFSTOPPED, WIFCONTINUED

StackOverflow https://stackoverflow.com/questions/907867

  •  05-09-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

#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;
}

Другие советы

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

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

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

Структура, подобная приведенной ниже, позволит вам проверить результаты 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 перечислит все сигналы, которые можно отправить.

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

РЕДАКТИРОВАТЬ

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top