How could I track down the death of a child process without making the parent process wait until the child process got killed?
I am trying a client-server scenario where the server accepts the connection from a client and forks a new process for each and every connection it accepts.
I am ignoring SIGCHLD signals to prevent zombie creation.
signal(SIGCHLD, SIG_IGN);
while(1)
{
accept();
clients++;
if(fork() ==0)
{
childfunction();
clients--;
}
else
{
}
}
The problem in the above scenario is that if the child process gets killed in the childfunction()
function, the global variable clients
is not getting decremented.
NOTE: I am looking for a solution without using SIGCHLD signal ... If possible
The variable 'clients' are in different process address spaces after fork() and when you decrement the variable in the child, this will not affect the value in the parent. I think you need to handle SIGCHLD to handle the count correctly.
You don't want a zombie. If a child process dies and the parent is still RUNNING but never issues a
wait()
/waitpid()
call to harvest the status, the system does not release the resources associated with the child and a zombie/defunct process is left in the proc table.Try changing your
SIGCHLD
handler to something closer to the following:You could optionally mask/block additional
SIGCHLD
signals during execution of the signal handler usingsigprocmask()
. The blocked mask must be returned to its original value when the signal handling routine has finished.If you really don't want to use a
SIGCHLD
handler, you could try adding the child processing loop somewhere where it would be called regularly and poll for terminated children.None of the solutions so far offer an approach without using SIGCHLD as the question requests. Here is an implementation of an alternative approach using poll as outlined in this answer (which also explains why you should avoid using SIGCHLD in situations like this):
(Note: I omitted some best practices like error-checking and cleaning up file descriptors for brevity)
And here is some sample output from running the program with the
printf
statements uncommented:Typically you write a handler for
SIGCHLD
which callswaitpid()
on pid-1
. You can use the return value from that to determine what pid died. For example:Alternatively you can call
waitpid(pid, &status, 0)
with the child's process ID specified, and synchronously wait for it to die. Or useWNOHANG
to check its status without blocking.