As stated in accept()
man page in RETURN VALUE
section:
Error handling
Linuxaccept()
(andaccept4()
) passes already-pending network errors on the new socket as an error code fromaccept()
. This behavior differs from other BSD socket implementations. For reliable operation the application should detect the network errors defined for the protocol afteraccept()
and treat them likeEAGAIN
by retrying. In the case of TCP/IP, these areENETDOWN
,EPROTO
,ENOPROTOOPT
,EHOSTDOWN
,ENONET
,EHOSTUNREACH
,EOPNOTSUPP
, andENETUNREACH
.
Does this mean one must check the value of errno
right after the accept()
returns and before checking the return value of accept()
? if yes, and if errno
is set what steps must be taken?
here’s a snippet of my code handling accept()
:
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if((errno == ENETDOWN || errno == EPROTO || errno == ENOPROTOOPT || errno == EHOSTDOWN || errno == ENONET || errno == EHOSTUNREACH || errno == EOPNOTSUPP || errno == ENETUNREACH)) return; if (newsockfd < 0) { // error } else if(newsockfd > 0) { // accepted a new connection } else { // blah blah blah }
I have concluded that in this case one might try again in a while. Is my conclusion correct?
Advertisement
Answer
First, you check accept()
return value. If accept()
return value is less than 0
, then you should check errno
. If it is ENETDOWN
, EPROTO
, ENOPROTOOPT
, EHOSTDOWN
, ENONET
, EHOSTUNREACH
, EOPNOTSUPP
, or ENETUNREACH
, then you may call accept()
again. Otherwise something bad has happened and you should stop calling accept()
(you’ve passed bad listen socket as accept()
‘s parameter, for example).
That’s how I understand the code.
And here is how the error handling may be done:
while (running) { newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0) { // error perror ("accept"); if((errno == ENETDOWN || errno == EPROTO || errno == ENOPROTOOPT || errno == EHOSTDOWN || errno == ENONET || errno == EHOSTUNREACH || errno == EOPNOTSUPP || errno == ENETUNREACH)) { continue; } exit (EXIT_FAILURE); } // accepted a new connection // blah blah blah }