How to Spawn Child Processes that Don't Die with Parent?

前端 未结 6 1198
说谎
说谎 2021-01-18 11:09

I have a C++ program that acts as a watchdog over others. If it detects that a process is no longer running, it restarts it via system. The problem is, if I kil

6条回答
  •  南笙
    南笙 (楼主)
    2021-01-18 11:53

    This one is a bit old but didn't get a complete answer. Here is what I have done on an embedded system to spawn a bash child with no relation to the parent. Note that I execl a bash shell and then run my command in another bash shell. This may not be necessary in your situation. For me it allowed me to do some I/O redirection that didn't work properly without it.

    The two important concepts are the setsid() and the double fork(). The combination of these two prevents a zombie from being created when the orphaned child completes, as well as preventing the orphaned child from being killed if the parent completes.

    There are many other issues that could come up, like inherited I/O handles, working directory, etc, but this code does the basic job.

    int spawn_orphan(char* cmd) {
        char command[1024]; // We could segfault if cmd is longer than 1000 bytes or so
        int pid;
        int Stat;
        pid = fork();
        if (pid < 0) { perror("FORK FAILED\n"); return pid; }
        if (pid == 0) { // CHILD
            setsid(); // Make this process the session leader of a new session
            pid = fork();
            if (pid < 0) { printf("FORK FAILED\n"); exit(1); }
            if (pid == 0) { // GRANDCHILD
                sprintf(command,"bash -c '%s'",cmd);
                execl("/bin/bash", "bash", "-c", command, NULL); // Only returns on error
                perror("execl failed");
                exit(1);
            }
            exit(0); // SUCCESS (This child is reaped below with waitpid())
        }
    
        // Reap the child, leaving the grandchild to be inherited by init
        waitpid(pid, &Stat, 0);
        if ( WIFEXITED(Stat) && (WEXITSTATUS(Stat) == 0) ) {
            return 0; // Child forked and exited successfully
        }
        else {
            perror("failed to spawn orphan\n");
            return -1;
        }
    }
    

提交回复
热议问题