The program initially asks the user to input the number of child processes to create. After creating the children, the parent sleeps and waits for all its children to terminate via a signal handler function 'handle_child' registered with SIGCHLD.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int to_kill;
void handle_child(int sig)
{
pid_t id = wait(NULL);
printf("Reaped child with PID = %d\n",id);
--to_kill;
if(to_kill == 0){
printf("~All children have been reaped successfully.. parent will now exit~\n");
exit(0);
}
}
int main()
{
pid_t id, parent_id = getpid();
int children, i;
signal(SIGCHLD, handle_child);
printf("Enter number of child processes to spawn: ");
scanf("%d",&children);
to_kill = children;
for(i = 0; i < children; ++i){
id = fork();
if(id == 0){
printf("New child with pid = %d\n",getpid());
sleep(2);
return 0;
}
sleep(1);
}
sleep(30);
return 0;
}
The problem I'm facing is that the parent often exits without reaping all of its children. Some of the times the program runs perfectly well, and at other times it ends abruptly. What is exactly happening here?
One of the instances of the erroneous output:
Enter number of child processes to spawn: 4
New child with pid = 6458
New child with pid = 6459
Reaped child with PID = 6458
New child with pid = 6461
Reaped child with PID = 6459
New child with pid = 6462
Reaped child with PID = 6461
nishad@nishad-Lenovo-B575:~$
I think the call to sleep(30) is interrupted by the SIGCHLD interrupt so it will not sleep for 30s but return immediately after the signal handler is called.
To get it right you will need to sleep in a loop:
tosleep = 30;
while (tosleep > 0) {
tosleep = sleep(tosleep);
}