我有一個創建TCP服務器的程序。當accept()連接到客戶端時,我fork()它並處理連接。當客戶端由於SIGCHLD而離開它時調用waitpid(),但是這導致accept()中的EINTR。我的問題是應該如何處理?我讀過很多不同的方法。在Linux中處理SIGCHLD,EINT和accept()的正確方法
大多數人說忽略它的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'。請參閱http://stackoverflow.com/questions/17015830/how-can-i-prevent-zombie-child-processes – Barmar