首页 文章

进程组中的进程是否应该与Unix / Linux中的父进程一起终止?

提问于
浏览
6

我有一个父进程可能产生许多子进程的情况 . 我想要实现的是,如果父进程被终止或者它退出,那么它的所有子进程应该与父进程终止 .

在帖子(下面的链接)中,我找到了通过让父进程成为组长来存档的建议 . 如果我理解正确,这也是过程组的主要目的 . 我对吗?
Post也提到了prctl(PR_SET_PDEATHSIG,SIGHUP);和其他一些方法,但它们是以太网操作系统特定的,否则不会如此优雅 .

我已经写了一个小的演示来试图更好地理解事物,但它并不像我期望的那样工作 . 我究竟做错了什么?

//https://www.andrew.cmu.edu/course/15-310/applications/homework/homework4/terminalgroups1.html
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <stddef.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/termios.h>

int main()
{
    int status;
    int cpid;
    int ppid;

    ppid = getpid();
    printf("parent: %d\n", ppid);

    if (!(cpid=fork()))
    {
        printf("child: %d\n", getpid());
        if(setpgid(0,ppid) == -1)
           printf("child setpgid errno %s\n", strerror(errno));
        else
           printf("child gid %d\n", getpgid(0));
        pause();
        printf("child exited\n");
        exit (-1);
     }

     if (cpid < 0)
         exit(-1);

     setpgid(0, ppid);
     if(setpgid(0,0) == -1)
         printf("parent setpgid erno %s\n", strerror(errno));
     else
         printf("parrent gid %d\n", getpgid(0));


     sleep(7);
     printf("parent exit\n");
     exit(0);
}

这篇文章涉及以下建议:* How to make child process die after parent exits?

2 回答

  • 4

    请注意,仅在非常有限的情况下才会向子进程发送信号 . POSIX说:

    如果该过程是控制过程,则应将SIGHUP信号发送到属于呼叫过程的控制终端的前台进程组中的每个进程 . 如果该过程是控制过程,则与会话相关联的控制终端应与会话解除关联,允许其通过新的控制过程获取 . 如果进程的退出导致进程组变为孤立,并且如果新的孤立进程组的任何成员停止,则应将新的孤立进程组中的每个进程发送一个SIGHUP信号,后跟SIGCONT信号 . .

    controlling process的定义是:

    Build 与控制终端的连接的会话负责人 . 如果终端随后不再是该会话的控制终端,则会话领导者不再是控制过程 .

    通常,您的进程不会成为 Build 与控制终端(通常是您的shell)连接的会话负责人 .

    如果POSIX的另一部分适用,请通知我 .

    我对你的代码进行了一些测试( termkids.c ):

    #include "posixver.h"
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <signal.h>
    
    static void sigcatcher(int signum)
    {
    
      printf("%d: Signal caught: %d\n", (int)getpid(), signum);
      exit(1);
    }
    
    int main(void)
    {
        int cpid;
        int ppid;
    
        ppid = getpid();
        printf("Parent  PID:  %d\n", ppid);
        printf("Initial PGID: %d\n", (int)getpgid(0));
        if (setpgid(0, 0) != 0)
        {
          fprintf(stderr, "setpgid() failed (%d: %s)\n", errno, strerror(errno));
          return 1;
        }
        printf("Revised PGID: %d\n", (int)getpgid(0));
    
        if ((cpid=fork()) < 0)
        {
          fprintf(stderr, "fork() failed (%d: %s)\n", errno, strerror(errno));
          return 1;
        }
        else if (cpid == 0)
        {
            cpid = getpid();
            printf("Child PID:  %d\n", cpid);
            printf("Child PGID: %d\n", (int)getpgid(0));
            (void)signal(SIGTERM, sigcatcher);
            (void)signal(SIGHUP,  sigcatcher);
    
            pause();
            printf("%d: child exited\n", cpid);
            return(-1);
         }
    
         printf("Parent - sleeping\n");
         sleep(7);
         printf("Parent exits\n");
         return(0);
    }
    

    样本输出:

    $ ./termkids
    Parent  PID:  17701
    Initial PGID: 17701
    Revised PGID: 17701
    Parent - sleeping
    Child PID:  17702
    Child PGID: 17701
    Parent exits
    $ ps
      PID TTY          TIME CMD
      388 pts/5    00:00:00 bash
    17702 pts/5    00:00:00 termkids
    17707 pts/5    00:00:00 ps
    $ kill 17702
    17702: Signal caught: 15
    $
    

    请注意,在父进程完成后几分钟发送了 kill 17702 .

  • 1

    您可以使用atexit注册一个函数,该函数将SIGHUP信号发送到具有相同进程组ID的所有进程 . 当父母退出时,这会产生向所有孩子发送信号的预期效果 . 但是,请注意子项中的SIGHUP信号处理程序会导致子项立即退出,而不会从pause()返回并打印子项退出消息 .

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <stddef.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/wait.h>
    #include <sys/ioctl.h>
    #include <sys/termios.h>
    #include <sys/types.h>
    
    void killall() 
    {
        kill(0, SIGHUP);
    }
    
    int main()
    {
        int status;
        int cpid;
        int ppid;
    
        if (atexit(killall) != 0)
        {
            fprintf(stderr, "atexit failed with %d", errno);
            exit(-1);
        }
    
        ppid = getpid();
        printf("parent: %d\n", ppid);
    
        if (!(cpid=fork()))
        {
           printf("child: %d\n", getpid());
           if(setpgid(0,ppid) == -1)
               printf("child setpgid errno %s\n", strerror(errno));
           else
               printf("child gid %d\n", getpgid(0));
           pause();
           printf("child exited\n");
           exit (-1);
         }
    
         if (cpid < 0)
             exit(-1);
    
         setpgid(0, ppid);
         if(setpgid(0,0) == -1)
             printf("parent setpgid erno %s\n", strerror(errno));
         else
             printf("parent gid %d\n", getpgid(0));
    
    
         sleep(7);
         printf("parent exit\n");
         exit(0);
    }
    

相关问题