【问题标题】:why SIGHUP signal not received when becoming an Orphaned Process Group为什么成为孤立进程组时未收到 SIGHUP 信号
【发布时间】:2013-11-03 18:48:40
【问题描述】:

在关于orphaned process groups 的GNU libc 手册中,它提到:

“process groups that continue running even after the session leader 
has terminated are marked as orphaned process groups. 

When a process group becomes an orphan, its processes are sent a SIGHUP 
signal. Ordinarily, this causes the processes to terminate. However, 
if a program ignores this signal or establishes a handler for it 
(see Signal Handling), it can continue running as  in the orphan process
 group even after its controlling process terminates; but it still 
cannot access the terminal any more. ”

我写了一个测试程序,但是当进程组成为孤儿时,它的进程没有收到 SIGHUP 信号。我想知道为什么?

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>


static void  
sig_hup(int signo) //**never get called ???**
{
    printf("SIGHUP received, pid = %ld\n", (long)getpid());
}

static void
pr_ids(char *name)
{
    printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n",
        name, (long)getpid(), (long)getppid(), (long)getpgrp(),
        (long)tcgetpgrp(STDIN_FILENO));
    fflush(stdout);
}

int
main(void)
{
    char    c;
    pid_t   pid;

    pr_ids("parent");
    pid = fork();
    if (pid > 0) {       // parent 
        sleep(5);
        exit(0);         // parent exit;
    } else {
        pr_ids("child");
        setsid();        //create new session, and "child" becomes the session leader
        pid = fork();
        if(pid>0) {
            sleep(20);
            exit(0);     // "child" exit
                         // so the process group become an orphan process group
        }
        else{
            pr_ids("grandson");
            signal(SIGHUP, sig_hup);    // establish signal handler 
            sleep(60);                  // now becoming orphan process group
            printf("end\n");
        }
    }
    exit(0);
}

【问题讨论】:

    标签: c linux process jobs


    【解决方案1】:

    如果孤立进程组在成为孤立进程时被停止,则会得到SIGHUP,后跟SIGCONT

    睡眠不够,你需要:

    kill(getpid(), SIGSTOP); //or raise(SIGSTOP);
    

    除此之外,如果孤立是由 setsid()setprgrp() 引起的,POSIX 不要求发送 SIGHUPSIGCONT,因为它不是由退出进程引起的,因为它不是无辜地不知道的退出进程作业控制(参见http://pubs.opengroup.org/onlinepubs/9699919799/functions/_exit.html)。

    但是,如果在孩子中使用kill(getpid(), SIGSTOP) 而不是sleep(60),即使您不调用setsid(),您的程序也会停止孤儿。

    #define _GNU_SOURCE
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <signal.h>
    
    static void  
    sig_hup(int signo) //**never get called ???**
    {
        printf("SIGHUP received, pid = %ld\n", (long)getpid());
    }
    
    static void
    pr_ids(char *name)
    {
        printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n",
            name, (long)getpid(), (long)getppid(), (long)getpgrp(),
            (long)tcgetpgrp(STDIN_FILENO));
        fflush(stdout);
    }
    
    int
    main(void)
    {
        pid_t   pid;
    
        pr_ids("parent");
        pid = fork();
        if (pid > 0) {       // parent 
            sleep(5);
            _exit(0);         // parent exit;
        } else {
            pr_ids("child");
    
            /*setsid();        //create new session, and "child" becomes the session leader*/
    
            pid = fork();
            if(pid>0) {
                sleep(2);
                exit(0);     // "child" exit
                             // so the process group become an orphan process group
            }
            else{
                pr_ids("grandson");
                signal(SIGHUP, sig_hup);    // establish signal handler 
                kill(getpid(), SIGSTOP);
                printf("end\n");
            }
        }
        exit(0);
    }
    

    在父母去世 (5s) 后,应该在孩子中给你一个SIGHUP

    【讨论】:

      【解决方案2】:

      该文档部分专门讨论了一个进程的控制终端的丢失——通常是由于调制解调器挂断或虚拟等价物(结束 ssh 会话等)。 (我认为文档中的措辞可以在这里改进)。当你在这里使用setsid()时,在setsid()返回时你放弃了对控制终端的访问,所以从那里开始没有控制终端丢失。

      您可以open() 一个 tty 设备(例如 pty 从站)来获得一个控制终端(注意您可能还需要做一些额外的操作——FreeBSD 需要一个TIOCSCTTY ioctl),然后再次失去它,然后然后你应该得到SIGHUP信号。

      【讨论】:

        猜你喜欢
        • 2013-07-20
        • 1970-01-01
        • 2011-11-24
        • 1970-01-01
        • 1970-01-01
        • 2021-12-13
        • 1970-01-01
        • 1970-01-01
        • 2021-02-03
        相关资源
        最近更新 更多