From 394eec1068f1caea4c6ac4a3f2191eaef2a6719e Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Mon, 15 Apr 2002 23:34:17 +0000 Subject: [PATCH] Fix for EINTR returns from Win9X socket operations: 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 | 20 +++++++++++++++++++- src/interfaces/libpq/fe-misc.c | 24 ++++++++++++------------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 772e54b8db..9864aad9bf 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -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; diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 5f90547d60..190d378fd9 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -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));