5

我正在使用 waitpid() 和 signal() 并且我正在寻找可靠的测试用例来返回 WIFSIGNALED(status) = WIFSTOPPED(status) = WIFCONTINUED (status) = true 但找不到任何...

请告诉我如何确保那些返回 true 以便我可以调试我的代码?

此外,关于我应该使用 signal() 捕获哪些信号来测试这些宏的一些提示会很有帮助......

4

4 回答 4

6
#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;
}
于 2009-05-26T00:26:14.540 回答
3

处理 WIFSIGNALED 很容易。kill()子进程可以通过系统调用自杀。您还可以检查核心转储——一些信号会创建它们(SIGQUIT、IIRC);有些信号没有(SIGINT)。

处理 WIFSTOPPED 可能更难。尝试的简单步骤是让孩子kill()再次通过系统调用向自己发送 SIGSTOP。实际上,我认为这应该有效。请注意,您可能需要检查 SIGTTIN 和 SIGTTOU 和 SIGTSTOP - 我相信他们算作 WIFSTOPPED。(也有可能 SIGSTOP 只有在由调试器发送到它通过非 POSIX 系统调用运行的进程时才能正常工作,ptrace().)

处理 WIFCONTINUED 是我认为父母必须做的事情;在检测到进程已停止后,您的调用代码应通过向其发送 SIGCONT 信号(kill()再次)使其继续。孩子自己无法实现这一点;它已停止。同样,我不确定是否有额外的皱纹需要担心——可能。

于 2009-05-25T23:57:40.463 回答
1

类似下面的框架将允许您检查wait()andwaitpid()调用的结果。

pid_t pid = fork();

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

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

您实际上不必捕获发送的信号(使用signal()或相关功能)。signal()安装一个覆盖特定信号默认行为的处理程序 - 因此,如果您想检查终止进程的信号,请选择具有该默认行为的信号 - “ man -s7 signal”将为您提供信号的默认行为的详细信息。

对于您提到的使用SIGSTOPfor WIFSTOPPED(status)SIGCONTforWIFCONTINUED (status)SIGINTfor的宏WIFSIGNALED(status)

如果您想要更灵活的测试,您可以使用 kill(请参阅“ man kill”)向您的进程发送信号。kill -l将列出所有可以发送的信号。

于 2009-05-25T21:31:16.843 回答
-1

在您的测试中,您可以 fork() 并向您的子进程发送特定信号?在这种情况下,您的子进程是测试用例吗?

编辑

我的回答是关于编写 C 测试。你分叉,获取你的子进程(安装了信号处理程序的进程)的 pid,然后你可以使用kill(2). 这样就可以测试退出状态

于 2009-05-25T20:30:06.640 回答