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

前端 未结 6 1195
说谎
说谎 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:30

    There's an execvp example in https://github.com/w-A-L-L-e/wash/blob/master/src/wash.cpp. Passing command line args is sometimes an issue with exec* functions from unistd and getting the environment passed can be some work. Anyway, hope it helps...

    0 讨论(0)
  • 2021-01-18 11:40

    You should avoid the use of system.

    Do not use system() from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might be used to subvert system integrity. Use the exec(3) family of functions instead.

    and also if you want to check the return value or anything else

    Just go for execl

    #include <unistd.h>
    #include <stdlib.h>
    pid_t pid = fork()
    if (pid == -1)
    {
       exit(EXIT_FAILURE);
    }
    else if (pid == 0)
    {
      if (execl("processname", "processname", "/path/to/processConfig.xml", NULL) == -1)
        exit(EXIT_FAILURE); 
    }
    else
    ...
    
    0 讨论(0)
  • 2021-01-18 11:46

    Try using system with setsid before the process name.

    system("setsid processname /path/to/processConfig.xml &");
    

    This will launch the program in a new session.

    0 讨论(0)
  • 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;
        }
    }
    
    0 讨论(0)
  • 2021-01-18 11:54

    Don't use system(...) it is not multi-threading safe.

    int pid = fork();
    
    if(pid==0)
    {
      int rc = execv("processname", "/path/to/processConfig.xml &");
      if(rc == -1)
      {
        printf(stderr, "processname failed to start. %d", errno);
      }
      ...
    }
    else
    {
      //continue with the parent
    }
    
    0 讨论(0)
  • 2021-01-18 11:55

    You may be interested by the daemon(3) library function (internally using two nested fork(2) syscalls). After that, use the relevant execve(2) syscall (or related exec(3) functions)...

    You should read Advanced Linux Programming for more.

    0 讨论(0)
提交回复
热议问题