Fix for EINTR returns from Win9X socket operations:
authorBruce Momjian
Mon, 15 Apr 2002 23:34:17 +0000 (23:34 +0000)
committerBruce Momjian
Mon, 15 Apr 2002 23:34:17 +0000 (23:34 +0000)
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 Ford

src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/fe-misc.c

index 772e54b8dbaf177d3be14035ee7486f831af090d..9864aad9bf89b9b032c421327a2c184080995f88 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.182 2002/03/02 00:49:22 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.183 2002/04/15 23:34:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -913,8 +913,13 @@ connectDBStart(PGconn *conn)
     * Thus, we have to make arrangements for all eventualities.
     * ----------
     */
+retry1:
    if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0)
    {
+       if (SOCK_ERRNO == EINTR)
+           /* Interrupted system call - we'll just try again */
+           goto retry1;
+
        if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == 0)
        {
            /*
@@ -949,9 +954,14 @@ connectDBStart(PGconn *conn)
                              SOCK_STRERROR(SOCK_ERRNO));
            goto connect_errReturn;
        }
+retry2:
        /* Now receive the postmasters response */
        if (recv(conn->sock, &SSLok, 1, 0) != 1)
        {
+           if (SOCK_ERRNO == EINTR)
+               /* Interrupted system call - we'll just try again */
+               goto retry2;
+
            printfPQExpBuffer(&conn->errorMessage,
                              libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
                              SOCK_STRERROR(SOCK_ERRNO));
@@ -2132,8 +2142,12 @@ PQrequestCancel(PGconn *conn)
               "PQrequestCancel() -- socket() failed: ");
        goto cancel_errReturn;
    }
+retry3:
    if (connect(tmpsock, &conn->raddr.sa, conn->raddr_len) < 0)
    {
+       if (SOCK_ERRNO == EINTR)
+           /* Interrupted system call - we'll just try again */
+           goto retry3;
        strcpy(conn->errorMessage.data,
               "PQrequestCancel() -- connect() failed: ");
        goto cancel_errReturn;
@@ -2150,8 +2164,12 @@ PQrequestCancel(PGconn *conn)
    crp.cp.backendPID = htonl(conn->be_pid);
    crp.cp.cancelAuthCode = htonl(conn->be_key);
 
+retry4:
    if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
    {
+       if (SOCK_ERRNO == EINTR)
+           /* Interrupted system call - we'll just try again */
+           goto retry4;
        strcpy(conn->errorMessage.data,
               "PQrequestCancel() -- send() failed: ");
        goto cancel_errReturn;
index 5f90547d604ded4295953e95d00f0515b43c073a..190d378fd9a2485c910ae78f7725ee3509abf7e9 100644 (file)
@@ -25,7 +25,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.68 2002/03/06 06:10:42 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.69 2002/04/15 23:34:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -361,7 +361,7 @@ pqReadReady(PGconn *conn)
    if (!conn || conn->sock < 0)
        return -1;
 
-retry:
+retry1:
    FD_ZERO(&input_mask);
    FD_SET(conn->sock, &input_mask);
    timeout.tv_sec = 0;
@@ -371,7 +371,7 @@ retry:
    {
        if (SOCK_ERRNO == EINTR)
            /* Interrupted system call - we'll just try again */
-           goto retry;
+           goto retry1;
 
        printfPQExpBuffer(&conn->errorMessage,
                          libpq_gettext("select() failed: %s\n"),
@@ -395,7 +395,7 @@ pqWriteReady(PGconn *conn)
    if (!conn || conn->sock < 0)
        return -1;
 
-retry:
+retry2:
    FD_ZERO(&input_mask);
    FD_SET(conn->sock, &input_mask);
    timeout.tv_sec = 0;
@@ -405,7 +405,7 @@ retry:
    {
        if (SOCK_ERRNO == EINTR)
            /* Interrupted system call - we'll just try again */
-           goto retry;
+           goto retry2;
 
        printfPQExpBuffer(&conn->errorMessage,
                          libpq_gettext("select() failed: %s\n"),
@@ -478,7 +478,7 @@ pqReadData(PGconn *conn)
    }
 
    /* OK, try to read some data */
-tryAgain:
+retry3:
 #ifdef USE_SSL
    if (conn->ssl)
        nread = SSL_read(conn->ssl, conn->inBuffer + conn->inEnd,
@@ -490,7 +490,7 @@ tryAgain:
    if (nread < 0)
    {
        if (SOCK_ERRNO == EINTR)
-           goto tryAgain;
+           goto retry3;
        /* Some systems return EAGAIN/EWOULDBLOCK for no data */
 #ifdef EAGAIN
        if (SOCK_ERRNO == EAGAIN)
@@ -531,7 +531,7 @@ tryAgain:
            (conn->inBufSize - conn->inEnd) >= 8192)
        {
            someread = 1;
-           goto tryAgain;
+           goto retry3;
        }
        return 1;
    }
@@ -564,7 +564,7 @@ tryAgain:
     * Still not sure that it's EOF, because some data could have just
     * arrived.
     */
-tryAgain2:
+retry4:
 #ifdef USE_SSL
    if (conn->ssl)
        nread = SSL_read(conn->ssl, conn->inBuffer + conn->inEnd,
@@ -576,7 +576,7 @@ tryAgain2:
    if (nread < 0)
    {
        if (SOCK_ERRNO == EINTR)
-           goto tryAgain2;
+           goto retry4;
        /* Some systems return EAGAIN/EWOULDBLOCK for no data */
 #ifdef EAGAIN
        if (SOCK_ERRNO == EAGAIN)
@@ -804,7 +804,7 @@ pqWait(int forRead, int forWrite, PGconn *conn)
 
    if (forRead || forWrite)
    {
-retry:
+retry5:
        FD_ZERO(&input_mask);
        FD_ZERO(&output_mask);
        FD_ZERO(&except_mask);
@@ -817,7 +817,7 @@ retry:
                   (struct timeval *) NULL) < 0)
        {
            if (SOCK_ERRNO == EINTR)
-               goto retry;
+               goto retry5;
            printfPQExpBuffer(&conn->errorMessage,
                              libpq_gettext("select() failed: %s\n"),
                              SOCK_STRERROR(SOCK_ERRNO));