How to make child process die after parent exits?

后端 未结 24 2173
天涯浪人
天涯浪人 2020-11-22 05:31

Suppose I have a process which spawns exactly one child process. Now when the parent process exits for whatever reason (normally or abnormally, by kill, ^C, assert failure o

24条回答
  •  庸人自扰
    2020-11-22 06:29

    Some posters have already mentioned pipes and kqueue. In fact you can also create a pair of connected Unix domain sockets by the socketpair() call. The socket type should be SOCK_STREAM.

    Let us suppose you have the two socket file descriptors fd1, fd2. Now fork() to create the child process, which will inherit the fds. In the parent you close fd2 and in the child you close fd1. Now each process can poll() the remaining open fd on its own end for the POLLIN event. As long as each side doesn't explicitly close() its fd during normal lifetime, you can be fairly sure that a POLLHUP flag should indicate the other's termination (no matter clean or not). Upon notified of this event, the child can decide what to do (e.g. to die).

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char ** argv)
    {
        int sv[2];        /* sv[0] for parent, sv[1] for child */
        socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
    
        pid_t pid = fork();
    
        if ( pid > 0 ) {  /* parent */
            close(sv[1]);
            fprintf(stderr, "parent: pid = %d\n", getpid());
            sleep(100);
            exit(0);
    
        } else {          /* child */
            close(sv[0]);
            fprintf(stderr, "child: pid = %d\n", getpid());
    
            struct pollfd mon;
            mon.fd = sv[1];
            mon.events = POLLIN;
    
            poll(&mon, 1, -1);
            if ( mon.revents & POLLHUP )
                fprintf(stderr, "child: parent hung up\n");
            exit(0);
        }
    }
    

    You can try compiling the above proof-of-concept code, and run it in a terminal like ./a.out &. You have roughly 100 seconds to experiment with killing the parent PID by various signals, or it will simply exit. In either case, you should see the message "child: parent hung up".

    Compared with the method using SIGPIPE handler, this method doesn't require trying the write() call.

    This method is also symmetric, i.e. the processes can use the same channel to monitor each other's existence.

    This solution calls only the POSIX functions. I tried this in Linux and FreeBSD. I think it should work on other Unixes but I haven't really tested.

    See also:

    • unix(7) of Linux man pages, unix(4) for FreeBSD, poll(2), socketpair(2), socket(7) on Linux.

提交回复
热议问题