[patch] fe-connect.c doesn't handle EINTR correctly - Mailing list pgsql-hackers
From | David Ford |
---|---|
Subject | [patch] fe-connect.c doesn't handle EINTR correctly |
Date | |
Msg-id | 3C92DBB9.8050902@blue-labs.org Whole thread Raw |
Responses |
Re: [PATCHES] [patch] fe-connect.c doesn't handle EINTR correctly
|
List | pgsql-hackers |
Last year we had a drawn out discussion about this and I created a patch for it. I never noticed that the patch didn't go in until I installed 7.2 the other day and realised that fe-connect.c never was fixed. Here is the patch again. It is against CVS 3/16/2002. This time I only rewrote the connect procedure at line 912, I leave it up to the regular hackers to copy it's functionality to the SSL procedure just below it. In summary, if a software writer implements timer events or other events which generate a signal with a timing fast enough to occur while libpq is inside connect(), then connect returns -EINTR. The code following the connect call does not handle this and generates an error message. The sum result is that the pg_connect() fails. If the timer or other event is right on the window of the connect() completion time, the pg_connect() may appear to work sporadically. If the event is too slow, pg_connect() will appear to always work and if the event is too fast, pg_connect() will always fail. David Index: src/interfaces/libpq/fe-connect.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v retrieving revision 1.181 diff -u -r1.181 fe-connect.c --- src/interfaces/libpq/fe-connect.c 2001/11/11 02:09:05 1.181 +++ src/interfaces/libpq/fe-connect.c 2002/03/16 05:17:47 @@ -909,29 +909,48 @@ * Thus, we have to make arrangements for all eventualities. * ---------- */ - if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0) - { - if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == 0) - { - /* - * This is fine - we're in non-blocking mode, and the - * connection is in progress. - */ - conn->status = CONNECTION_STARTED; - } - else - { - /* Something's gone wrong */ - connectFailureMessage(conn, SOCK_ERRNO); - goto connect_errReturn; + do { + int e; + e=connect(conn->sock, &conn->raddr.sa, conn->raddr_len) + + if(e < 0) { + switch (e) { + case EINTR: + /* + * Interrupted by a signal, keep trying. This handling is + * required because the user may have turned on signals in + * his program. Previously, libpq would erronously fail to + * connect if the user's timer event fired and interrupted + * this syscall. It is important that we don't try to sleep + * here because this may cause havoc with the user program. + */ + continue; + break; + case 0: + case EINPROGRESS: + case EWOULDBLOCK: + /* + * This is fine - we're in non-blocking mode, and the + * connection is in progress. + */ + conn->status = CONNECTION_STARTED; + break; + default: + /* Something's gone wrong */ + connectFailureMessage(conn, SOCK_ERRNO); + goto connect_errReturn; + break; + } + } else { + /* We're connected now */ + conn->status = CONNECTION_MADE; } - } - else - { - /* We're connected already */ - conn->status = CONNECTION_MADE; - } + + if(conn->status == CONNECTION_STARTED || conn->status == CONNECTION_MADE) + break; + } while(1); + #ifdef USE_SSL /* Attempt to negotiate SSL usage */ if (conn->allow_ssl_try)
pgsql-hackers by date: