I have a program that creates a TCP server. When the accept() connects to a client, I fork() it and handle the connection. When that client leaves it calls the waitpid() because of the SIGCHLD, but this causes a EINTR in the accept(). My question is how should this be handled? I've read so many different ways.
Most say to ignore it the EINT and try the accept() again. I've even seen a macro to do just that: TEMP_FAILURE_RETRY(). Some say to set the sigaction flags SA_RESTART and SA_NOCLDSTOP. I've tried that and it introduces other errors (errno = ECHILD). Also, how should the child exit? I've seen both _exit(0) and 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);
}
}
}
The SIGCHLD handling is:
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);
}