>
>
>This does not actually *say* that the appropriate behavior after EINTR
>is to retry, but reading between the lines one might infer that it will
>work like the nonblocking case, wherein a retry of connect tries to link
>to the existing connection attempt, not start a new one.
>
>What's more important is that a retry will expose the possibility of
>getting EALREADY or EISCONN. EALREADY certainly must be treated as
>success the same as EINPROGRESS (if it exists on a given platform ---
>better #ifdef it I think). Not so sure about EISCONN; does that imply
>"you moron, this socket's been open forever", or does it get returned on
>the first iteration that doesn't return EALREADY?
>
Not to worry. EINPROGRESS, etc, are normally used for select() and
return the current state of the connection attempt. connect() in
blocking mode will normally only return when it is interrupted or
complete. In non-blocking mode, it will return immediately with errno
set to EALREADY, in which case you should spin on the socket connection
attempt and wait until it returns a good status, i.e. return value=0, or
if you happen to make a mistake and drop that iteration, EISCONN.
Those of you who are interested in socket operations would probably
enjoy reading TCP/IP Illustrated, I believe the most recent version is
#3, sorry I don't have the ISBN handy but most libraries should have v2.
As to your last concern Tom, the cycle should be: return=-1 [repeats
until connection fails or succeeds], return=0 on success, or -1 on
failure w/ errno set to appropriate fault, and afterwards, either return
-1 with errno=EISCONN (already connected with prior success), or
appropriate fault.
The important part is that if the socket successfully connects, it will
return a 0. That should be the last iteration of your spin on that
connect call. If you have a mistake in your code and you keep spinning
on a successfully connected socket, yes you will get EISCONN, i.e.
"hello..the socket is still connected" :)
Thus a simplified loop should look like this:
do { int r;
r=connect(...); if(!r) /* we're connected, r=0. exit the loop */ break; switch(errno) { /*
connectreturns 0 or -1, so this must be -1 */ case EINTR: /* we were interrupted by a signal */
continue; default: error_log(logfd, "Error connecting, kernel said: %s",
strerror(errno)); r=-2; /* jump out of the loop */ break; }
} while(r==-1):
This will continue trying the connect call as long as it hasn't returned
a failure message and the errno is EINTR. All other -1 return values
will exit the loop. As soon as it has connected properly it will also
exit the loop.
David