简体   繁体   中英

Linux: Get the grandchild's pid C++

I want to create a function where I pass a structure which will store the pid of the process that is spawned.

bool spawnHost(string ttyNumber, DeviceData &deviceData)    
{
   pid_t processID = fork();
   pid_t hostProcessID = -1;
   if (processID == -1)
   {
       printf("PID:%d-> Unable to fork a new process. Error: %s", getpid(), strerror(errno));
       return false;
   }
   else if (!processID)
   {
       printf("PID:%d-> First child spawned. In Parent: %s", getpid(), processID);
       signal(SIGCHLD, SIG_IGN);
       hostProcessID = fork();
       if (hostProcessID == -1)
       {
          printf("PID:%d-> Unable to fork a new process. Error: %s", getpid(), strerror(errno));
          return false;
       }
       else if (!hostProcessID)
       {
          printf("PID:%d-> Starting %s at tty:%s", getpid(), hostAppPath.c_str(), ttyNumber.c_str());
          char *args[] = { (char *) hostAppPath.c_str(), (char *) ttyNumber.c_str(), NULL };
          execvp(hostAppPath.c_str(), args);
       }
       else
       {
          printf("PID:%d-> First child spawned. In child: %s", getpid(), hostProcessID);            
          sleep(5);
          exit(0);
       }
   }
   else
   {
      int childStatus;
      waitpid(processID, &childStatus, 0);
      if (WIFEXITED(childStatus))
         printf("PID:%d has exited with exit code %d\n", processID, WEXITSTATUS(childStatus));

      deviceData.setProcessID(hostProcessID);
      return true;
    }
}

The requirement here is that the host process (spawned in the second fork) shall not die, even if the parent process dies, and the pid of the host process shall be stored in a structure which was passed to the spawnHost() function. currently I am not able to get the pid. Is there something wrong with what I am dong?

I even tried the below approach:

bool spawnHost(string ttyNumber, DeviceData deviceData)
{   
    string hostAppPath = EXE_PATH;

    signal(SIGCHLD, SIG_IGN);
    pid_t processID = fork();

    if (processID == -1)
    {
        printf("PID:%d-> Unable to fork a new process. Error: %s", getpid(), strerror(errno));
        return false;
    }
    else if (!processID)
    {
        signal(SIGCHLD, SIG_IGN);
        processID = fork();
        if (processID == -1)
        {
            printf("PID:%d-> Unable to fork a new process. Error: %s", getpid(), strerror(errno));
            return false;
        }
        else if (!processID)
        {
            if (setsid() < 0)
            {
                printf("PID:%d-> Unable to set new session ID. Error: %s", getpid(), strerror(errno));
                return false;
            }

            printf("PID:%d-> Starting %s at tty:%s", getpid(), hostAppPath.c_str(), ttyNumber.c_str());
            char *args[] = { (char *) hostAppPath.c_str(), (char *) ttyNumber.c_str(), NULL };
            execvp(hostAppPath.c_str(), args);
        }
        else
        {
            deviceData.setProcessID(processID);
            exit(0);
        }
    }
    else
    {       
        return true;
    }   
    return true;
}

So thanks to @o11c The answer that I implemented is:

bool spawnHost(string ttyNumber, DeviceData &deviceData)
{
    int pipefd[2];      
    string hostAppPath = HOST_PATH_PREFIX + HOST_NAME + BUILD_DIR_STRING + HOST_NAME;

    if (pipe(pipefd) == -1)
    {
        printf("PID:%d-> IPC not possible as pipe failed");
        return false;
    }

    signal(SIGCHLD, SIG_IGN);
    pid_t processID = fork();

    if (processID == -1)
    {
        printf("PID:%d-> Unable to fork a new process. Error: %s", getpid(), strerror(errno));
        return false;
    }

    else if (!processID)
    {
        signal(SIGCHLD, SIG_IGN);
        processID = fork();
        if (processID == -1)
        {
            return false;
        }
        else if (!processID)
        {
            if (setsid() < 0)
            {
                printf("PID:%d-> Unable to set new session ID. Error: %s", getpid(), strerror(errno));
                return false;
            }
            char *args[] = { (char *) hostAppPath.c_str(), (char *) ttyNumber.c_str(), NULL };
            execvp(hostAppPath.c_str(), args);
        }
        else
        {
            /// Write the host pid to the pipe
            close(pipefd[0]);
            write(pipefd[1], &processID, sizeof(processID));
            close(pipefd[1]);
            exit(0);
        }
    }
    else
    {
        close(pipefd[1]); /* Close unused write end */
        read(pipefd[0], &processID, sizeof(processID));
        close(pipefd[0]);
        wait(NULL);

        deviceData.setProcessID(processID);
        return true;
    }   
    return true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM