[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  (Bruce Momjian <pgman@candle.pha.pa.us>)
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:

Previous
From: Greg Copeland
Date:
Subject: Re: User Level Lock question
Next
From: "Vadim Mikheev"
Date:
Subject: Re: [BUGS] Bug #613: Sequence values fall back to previously chec