I am using connect_nonb() from Stevens, UNIX Network programming:
int
connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec)
{
int flags, n, error;
socklen_t len;
fd_set rset, wset;
struct timeval tval;
flags = Fcntl(sockfd, F_GETFL, 0);
Fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
error = 0;
if ( (n = connect(sockfd, saptr, salen)) < 0)
if (errno != EINPROGRESS)
return(-1);
/* Do whatever we want while the connect is taking place. */
if (n == 0)
goto done; /* connect completed immediately */
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
wset = rset;
tval.tv_sec = nsec;
tval.tv_usec = 0;
if ( (n = Select(sockfd+1, &rset, &wset, NULL,
nsec ? &tval : NULL)) == 0) {
close(sockfd); /* timeout */
errno = ETIMEDOUT;
return(-1);
}
if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
len = sizeof(error);
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
return(-1); /* Solaris pending error */
} else
err_quit("select error: sockfd not set");
done:
Fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
if (error) {
close(sockfd); /* just in case */
errno = error;
return(-1);
}
return(0);
}
This function allows a custom timeout of connect(). If, whilst blocking in select() waiting for the connect to succeed, a signal is received, select() exits with -1 (EINTR). At this point the select() timeout has not expired, the connect has not succeeded (i.e. the target host could be disconnected) but the subsequent getsockopt() does not return an error.
Should getsockopt() return an error or should the Stevens code check the return code (and errno) of select()?
Currently when connecting to a non-existent host and a signal interrupts select() this function returns success incorrectly.
I'm not sure what
Select()is. I assume it's some kind of thin wrapper aroundselect().In most applications, whenever
select()fails withEINTR, you should silently loop and callselect()again, possibly after recalculating the timeout to account for the fact that some time has elapsed in the prior call toselect().This case is no exception.
select()should be in a loop.