我正在尝试使我的server.c程序能够处理僵尸进程。最初,我从linuxhowtos.org/C_C++/socket找到了signal(SIGCHLD,SIG_IGN);
行。这就像一个魅力。我可以与客户端连接,然后关闭客户端,一切仍然顺利运行。
但是,我正在尝试用SigCatcher替换SIG_IGN,如文中所述,当客户端关闭时,我的服务器程序开始变得干扰(它无限地继续接收“2”并输出)。
我同时尝试了wait3(NULL,WNOHANG,NULL)
和wait(-1)
,但这些都没有解决问题。我究竟应该在这做什么?
void *SignalCatcher(int n)
{
wait3(NULL,WNOHANG,NULL);
}
这就是我的主要观点:
//signal(SIGCHLD, SIG_IGN);
signal(SIGCHLD, SignalCatcher);
for(;;)
{
clilen=sizeof(cliaddr);
connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
if ((childpid = fork()) == 0)
{
close (listenfd);
for(;;)
{
n = recvfrom(connfd,mesg,1000,0,(struct sockaddr*)&cliaddr,&clilen);
write(connfd , "" , 1);
mesg[n] = 0;
printf("Received the following:\n");
printf("%s",mesg);
}
}
close(connfd);
}
答案 0 :(得分:1)
void *SignalCatcher(int n)
{
wait3(NULL,WNOHANG,NULL);
}
应该是:
void SignalCatcher(int signum)
{
wait3(NULL,WNOHANG,NULL);
}
返回类型在信号处理程序中非常关键(因为调用约定与普通函数调用不同)。在任何情况下,编译器应至少发出警告。
第二:在循环中,你应该处理来自recvfrom()的错误返回。 (并写())
for(;;) {
n = recvfrom(connfd,mesg,1000,0,(struct sockaddr*)&cliaddr,&clilen);
if (n == -1 && errno = EAGAIN) continue;
else if (n == 0) break; // for non-blocking sockets...
write(connfd , "" , 1);
mesg[n] = 0;
printf("Received the following: %s\n", mesg);
}
答案 1 :(得分:0)
为什么这么努力工作呢?只要孩子们一开始就把它们守护好(例如,在第一个孩子立即离开的时候分叉两次,而孙子继续将pid 1作为其父母。)除非有理由保留工人流程的父母,否则这将是大大简化了事情。