Checking the status of a child process in C++
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.
Alex
Updated on November 21, 2021Comments
-
Alex over 2 years
I have a program that uses
fork()
to create a child process. I have seen various examples that usewait()
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 about 13 yearsI'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 about 13 yearsHow do I know if I have gotten that signal?
-
Alex about 13 yearsSo 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 about 13 yearsNo, 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 about 13 yearsIf 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 about 13 yearsWell, what I mean is I made a
pid_t
to saypid=fork()
. Now to write code for my parent and child I have an if-else that checksif(pid)
to identify the parent process, because in the parent processpid
contains the child's pid number, and in the childpid
contains0
. So if I am understanding this correctly I believe that I should usepid
where you have said to useChildPID
. -
Erik about 13 years@Alex: Yes, your
pid
is the process ID of the child. -
Alex about 13 yearsThat 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 over 11 yearsU need to use getpid() to get the process id of the child. using a -1 in place of childpid would work
-
Alexander Shukaev almost 8 yearsWhat if
WIFSTOPPED
returnstrue
in theelse
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 theelse
clause. Same goes forWIFCONTINUED
.