You have an infinite sleep loop in your signal handler sigcallback
. Once a signal has been handled by that function, the process will never handle another SIGCHLD
signal again, since the signal handler never returns. This is likely the cause of your zombies.
You do not get one signal delivered for every exited child. If two children exit "simultaneously", you will only get a single SIGCHLD
delivered. So, when you wait in your signal handler (either of them), you should wait in a loop to reap all the children that have exited. Something along the lines of:
for (;;) {
pid_t p = waitpid(-1, 0, WNOHANG);
if (p <= 0) break;
/* ... */
}
When your process exits, the children of that process will be inherited by the init process, so they will be reaped properly. However, your infinite loop prevented 3 things:
- It would not reap simultaneously exited children.
- It would not reap any more children after reaping the first.
- It would not allow the process to exit, so the children could not be reaped by the init process.