Reputation: 4082
My question is I can't undertand why those code still generate zombie process. how can I fixed it? thanks.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
int count = 0;
/**
* signal callback
* @param signo
*/
void sigcallback(int signo) {
short stime = 5;
int status;
wait(&status);
while (1) {
printf("wake up,%d\n", getpid());
sleep((stime + 1) - (short) (time(NULL) % stime));
}
}
int call_cmd(void) {
count++;
int i;
pid_t pid;
signal(SIGCHLD, sigcallback);
for (i = 0; i < 3; i++) {
if ((pid = fork()) < 0) {
printf("error with fork\n");
exit(1);
} else if (pid > 0) {
waitpid(pid, NULL, WNOHANG);
} else {
printf("\t\t\tsid is %d,count is %d,pid is %d\n", getsid(getpid()), count, getpid());
}
}
return 1;
}
void notice_root(int signo) {
printf("execut root signal\n");
waitpid(0, NULL, 0);
}
int main(void) {
pid_t pid;
int i;
signal(SIGCHLD, notice_root);
for (i = 0; i < 2; i++) {
if ((pid = fork()) < 0) {
printf("error with fork\n");
exit(1);
} else if (pid > 0) {
exit(0);
} else {
setsid();
call_cmd();
}
}
return 0;
}
Upvotes: 1
Views: 1085
Reputation: 70362
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:
Upvotes: 3