信号始终由父进程捕获

时间:2016-03-17 15:13:51

标签: command-line process solaris signals fork

考虑在Solaris 11.3(系统(3C)的简化版本)下运行的以下代码:

int main(int argc, char **argv) {

     pid_t pid = fork();
     pid_t w;
     int status;
     if (pid == 0) {
             execvp(argv[1], argv + 1);
             perror("Failed to exec");
             exit(127);
     }
     if (pid > 0) {
             w = waitpid(pid, &status, 0);
             if (w == -1) {
                     perror("Wait: ");
                     exit(1);
             }
             else if (WIFEXITED(status) > 0) {
                     printf("\nFinish code: %d\n", WEXITSTATUS(status));
             }
             else {
                     printf("\nUnexpected termination of child process.\n");
             }
     }
     if (pid == -1) {
             perror("Failed to fork");
     }

 }

我得到的问题是,只要通过信号(例如,SIGINT)完成过程,就不会打印“意外终止”消息。

我看到它的方式,整个进程组从终端接收信号,在这种情况下,父进程只是在waitpid(2)返回之前终止(显然每次都会发生这种情况)。

如果是这种情况,我有一个后续问题。如何在不使用信号处理程序的情况下从父级检索有关终止子进程的信号的信息?例如,我可以添加另一个if-else块,其中WIFSIGNALED检查和WTERMSIG调用传递变量status(事实上,我做了,但是在用Ctrl + C终止时该计划没有提供任何输出)

那究竟是什么以及以何种顺序发生的?

2 个答案:

答案 0 :(得分:3)

你说,“...每当过程通过信号完成时 (例如,SIGINT)......“,但你不够具体 让任何人明确回答你的问题。 如果要使用kill命令向子进程发送信号, 你有一个奇怪的问题。 但是,如果我怀疑(正如你所说的那样) “整个过程组接收来自终端的信号”, 你只是输入 Ctrl + C ,这很简单:

  • 键入INTR,QUIT或SUSP字符时, 发送相应的信号(SIGINT,SIGQUIT或SIGTSTP) 同时到终端进程组中的所有进程。
    • 好的,严格说话,它不是同步。 它发生在终端驱动程序的循环中 (具体来说,我相信,“线路规则”处理程序),在内核中。 在此循环完成之前,不会发生用户进程执行。
  • 你说“......父进程只是终止了 在waitpid(2)返回之前(......每次,显然)。“ 从技术上讲,这是事实。 如上所述,进程组中的所有进程 (包括您的父进程和子进程)接收信号 (基本上)同时。 由于父母不处理信号本身, 它在可以进行任何处理之前终止 由孩子收到信号触发。
  • 你说“信号总是先由父进程捕获”。 没有;往上看。 并且流程以未指定的顺序终止 - 这可能是它们在流程表中出现的顺序 (这是不确定的), 或者由一些微妙的(也许是未记录的)方面决定 调度程序的算法。

相关的U& L问题:

答案 1 :(得分:1)

如果您通过另一个tty的“kill”发送信号,它是否正常工作?我在linux上试过这个。似乎行为相同。

如果将shell控制信号传递给进程组,我认为你是对的....你有一场比赛。您需要在父母中捕获并延迟它们。

我所做的就是做“./prog cat”

执行kill -SIGINT 工作正常。

执行control-C不打印任何内容。

在前面做一个setsid()有父终止,但是孩子继续运行。