Re: [patch] helps fe-connect.c handle -EINTR more gracefully - Mailing list pgsql-hackers

From David Ford
Subject Re: [patch] helps fe-connect.c handle -EINTR more gracefully
Date
Msg-id 3BD9C00D.2020804@blue-labs.org
Whole thread Raw
In response to [patch] helps fe-connect.c handle -EINTR more gracefully  (David Ford <david@blue-labs.org>)
Responses Re: [patch] helps fe-connect.c handle -EINTR more gracefully
List pgsql-hackers
>
>
>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




pgsql-hackers by date:

Previous
From: David Ford
Date:
Subject: Re: [patch] helps fe-connect.c handle -EINTR more gracefully
Next
From: Peter Eisentraut
Date:
Subject: Re: schema support, was Package support for Postgres