【发布时间】:2015-09-11 18:58:51
【问题描述】:
我有一个创建 TCP 服务器的程序。当 accept() 连接到客户端时,我 fork() 它并处理连接。当该客户端离开时,它会因为 SIGCHLD 而调用 waitpid(),但这会导致 accept() 中出现 EINTR。我的问题是应该如何处理?我读过很多不同的方式。
大多数人说忽略它 EINT 并再次尝试 accept()。我什至见过一个宏可以做到这一点:TEMP_FAILURE_RETRY()。有人说要设置 sigaction 标志 SA_RESTART 和 SA_NOCLDSTOP。我已经尝试过了,它引入了其他错误(errno = ECHILD)。另外,孩子应该如何退出? _exit(0) 和 exit(0) 我都见过。
int main( int argc, char *argv[] )
{
int sockfd, newsockfd, clilen;
struct sockaddr_in cli_addr;
int pid;
f_SigHandler();
sockfd = f_SetupTCPSocket();
clilen = sizeof(cli_addr);
while (1)
{
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
if( errno == EINTR ) continue;
else exit(1) ;
}
pid = fork();
if (pid == 0)
{
close(sockfd);
doprocessing();
close(newsockfd);
_exit(0);
}
else
{
close(newsockfd);
}
}
}
SIGCHLD 处理是:
void f_ChildHandler(int signal_number)
{
while (waitpid(-1, NULL, WNOHANG) > 0)
{
}
}
void f_SigHandler(void)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = f_ChildHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGCHLD, &sa, NULL);
}
【问题讨论】:
-
如果不需要获取退出状态,可以忽略
SIGCHLD。见stackoverflow.com/questions/17015830/…
标签: linux zombie-process sigchld eintr sigaction