Question

In the manual for GNU libc about orphaned process groups, it mentioned :

“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. ”

I write a test program, but when the process group becomes an orphan, its process didn't receive the SIGHUP signal. I am wondering why?

#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);
}
Était-ce utile?

La solution 2

That document section is talking specifically about the loss of a controlling terminal of a process that had one—usually by a modem hangup, or the virtual equivalent (ending an ssh session, etc). (I think the phrasing in the document could be improved here). When you use setsid() here, you give up access to the controlling terminal by the time setsid() returns, so there is no controlling terminal to lose from there forward.

You could open() a tty device (such as a pty slave) to gain a controlling terminal (note that you may have to do some additional operation as well—FreeBSD requires a TIOCSCTTY ioctl), then lose it again, and then you should get the SIGHUP signal.

Autres conseils

Orphaned process groups get SIGHUP followed by SIGCONT if they're stopped when they become orphaned.

Sleep is not enough, you need:

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

In addition to that, POSIX doesn't require that SIGHUP and SIGCONT be sent if the orphaning was caused by setsid() or setprgrp() because then it wasn't caused by an exiting process innocently unaware of job control (see http://pubs.opengroup.org/onlinepubs/9699919799/functions/_exit.html ).

However, with kill(getpid(), SIGSTOP) instead of that sleep(60) in the child, you will get a stopped orphan with your program even if you don't call 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);
}

should get you a SIGHUP in the child after the parent dies (5s).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top