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);
}