Checking the status of a child process in C++

34,919

Solution 1

Use waitpid() with the WNOHANG option.

int status;
pid_t result = waitpid(ChildPID, &status, WNOHANG);
if (result == 0) {
  // Child still alive
} else if (result == -1) {
  // Error 
} else {
  // Child exited
}

Solution 2

You don't need to wait for a child until you get the SIGCHLD signal. If you've gotten that signal, you can call wait and see if it's the child process you're looking for. If you haven't gotten the signal, the child is still running.

Obviously, if you need to do nothing unitl the child finishes, just call wait.

Solution 3

EDIT: If you just want to know if the child process stopped running, then the other answers are probably better. Mine is more to do with synchronizing when a process could do several computations, without necessarily terminating.

If you have some object representing the child computation, add a method such as bool isFinished() which would return true if the child has finished. Have a private bool member in the object that represents whether the operation has finished. Finally, have another method private setFinished(bool) on the same object that your child process calls when it finishes its computation.

Now the most important thing is mutex locks. Make sure you have a per-object mutex that you lock every time you try to access any members, including inside the bool isFinished() and setFinished(bool) methods.

EDIT2: (some OO clarifications)

Since I was asked to explain how this could be done with OO, I'll give a few suggestions, although it heavily depends on the overall problem, so take this with a mound of salt. Having most of the program written in C style, with one object floating around is inconsistent.

As a simple example you could have a class called ChildComputation

class ChildComputation {

    public:
    //constructor
    ChildComputation(/*some params to differentiate each child's computation*/) : 
        // populate internal members here {
    }
    ~ChildComputation();

    public:
    bool isFinished() {
        m_isFinished; // no need to lock mutex here, since we are not modifying data
    }

    void doComputation() {
        // put code here for your child to execute
        this->setFinished(true);
    }

    private:
    void setFinished(bool finished) {
        m_mutex.lock();
        m_isFinished = finished;
        m_mutex.unlock();
    }

    private:
    // class members
    mutex m_mutexLock; // replace mutex with whatever mutex you are working with
    bool m_isFinished;
    // other stuff needed for computation
}

Now in your main program, where you fork:

ChildComputation* myChild = new ChildComputation(/*params*/);
ChildPID= fork();
if (ChildPID == 0) {
   // will do the computation and automatically set its finish flag.
   myChild->doComputation();
}
else {
   while (1) { // your infinite loop in the parent
       // ...

       // check if child completed its computation
       if (myChild->isFinished()) {
           break;
       }
   }

   // at the end, make sure the child is no runnning, and dispose of the object
   // when you don't need it.
   wait(ChildPID);
   delete myChild;
}

Hope that makes sense.

To reiterate, what I have written above is an ugly amalgamation of C and C++ (not in terms of syntax, but style/design), and is just there to give you a glimpse of synchronization with OO, in your context.

Share:
34,919
Alex
Author by

Alex

Updated on November 21, 2021

Comments

  • Alex
    Alex over 2 years

    I have a program that uses fork() to create a child process. I have seen various examples that use wait() to wait for the child process to end before closing, but I am wondering what I can do to simply check if the file process is still running.

    I basically have an infinite loop and I want to do something like:

    if(child process has ended) break;

    How could I go about doing this?

  • Alex
    Alex about 13 years
    I'm not sure exactly how to make my child process into an object. This is the first time I have ever done this type of programming, so my understanding is still fairly basic. Right now I just have a main function that creates two pipes then forks and has an if-else statement using pid to separate the code for the parent and child processes. How could I go about making this object oriented?
  • Alex
    Alex about 13 years
    How do I know if I have gotten that signal?
  • Alex
    Alex about 13 years
    So the ChildPID is the one I am using to differentiate between parent and child and result is a new pid_t that makes a new sub-process that watches for the child to exit?
  • Erik
    Erik about 13 years
    No, ChildPID is the process ID of the child that fork() returned. waitpid() is just a function which returns a value: 0, ChildPid or -1
  • Alexander Kondratskiy
    Alexander Kondratskiy about 13 years
    If your problem is simple, maybe you don't even need to make it OO, I just assumed it since you put c++ as a tag. It really depends on the overall problem you are trying to solve. Erik's answer is the most appropriate for your current code. I'll add some stuff to my answer to clarify though.
  • Alex
    Alex about 13 years
    Well, what I mean is I made a pid_t to say pid=fork(). Now to write code for my parent and child I have an if-else that checks if(pid) to identify the parent process, because in the parent process pid contains the child's pid number, and in the child pid contains 0. So if I am understanding this correctly I believe that I should use pid where you have said to use ChildPID.
  • Erik
    Erik about 13 years
    @Alex: Yes, your pid is the process ID of the child.
  • Alex
    Alex about 13 years
    That makes sense. I suppose it really is more of a C issue than a C++ issue. I'm just used to using C++ and am including some C++ functions in my program, but this part of the program really is more C-like. I suppose in the future I will label it C/C++.
  • Access Denied
    Access Denied over 11 years
    U need to use getpid() to get the process id of the child. using a -1 in place of childpid would work
  • Alexander Shukaev
    Alexander Shukaev almost 8 years
    What if WIFSTOPPED returns true in the else clause? Semantically, this does not mean that the child process has exited, and is rather suspended. So I'd say for completeness, one should add the corresponding check into the else clause. Same goes for WIFCONTINUED.