У меня есть программа, которая создает TCP-сервер. Когда accept() подключается к клиенту, я fork() его и обрабатываю соединение. Когда этот клиент уходит, он вызывает waitpid() из-за SIGCHLD, но это вызывает EINTR в accept(). Мой вопрос в том, как это должно быть обработано? Я читал так много разных способов.
Большинство советует игнорировать EINT и снова попробовать accept(). Я даже видел макрос для этого: TEMP_FAILURE_RETRY(). Некоторые советуют установить флаги подписи 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/ - person Barmar   schedule 11.09.2015