Skip to content

Commit 2908a83

Browse files
committed
Code review for connection timeout patch. Avoid unportable assumption
that tv_sec is signed; return a useful error message on timeout failure; honor PGCONNECT_TIMEOUT environment variable in PQsetdbLogin; make code obey documentation statement that timeout=0 means no timeout.
1 parent bd19e8f commit 2908a83

File tree

2 files changed

+45
-30
lines changed

2 files changed

+45
-30
lines changed

src/interfaces/libpq/fe-connect.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.212 2002/10/16 04:38:00 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.213 2002/10/24 23:35:55 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -507,6 +507,9 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
507507
else
508508
conn->pgpass = strdup(DefaultPassword);
509509

510+
if ((tmp = getenv("PGCONNECT_TIMEOUT")) != NULL)
511+
conn->connect_timeout = strdup(tmp);
512+
510513
#ifdef USE_SSL
511514
if ((tmp = getenv("PGREQUIRESSL")) != NULL)
512515
conn->require_ssl = (tmp[0] == '1') ? true : false;
@@ -1051,32 +1054,29 @@ static int
10511054
connectDBComplete(PGconn *conn)
10521055
{
10531056
PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
1054-
1055-
time_t finish_time = -1;
1057+
time_t finish_time = ((time_t) -1);
10561058

10571059
if (conn == NULL || conn->status == CONNECTION_BAD)
10581060
return 0;
10591061

10601062
/*
1061-
* Prepare to time calculations, if connect_timeout isn't zero.
1063+
* Set up a time limit, if connect_timeout isn't zero.
10621064
*/
10631065
if (conn->connect_timeout != NULL)
10641066
{
10651067
int timeout = atoi(conn->connect_timeout);
10661068

1067-
if (timeout == 0)
1069+
if (timeout > 0)
10681070
{
1069-
conn->status = CONNECTION_BAD;
1070-
return 0;
1071+
/* Rounding could cause connection to fail; need at least 2 secs */
1072+
if (timeout < 2)
1073+
timeout = 2;
1074+
/* calculate the finish time based on start + timeout */
1075+
finish_time = time(NULL) + timeout;
10711076
}
1072-
/* Rounding could cause connection to fail;we need at least 2 secs */
1073-
if (timeout == 1)
1074-
timeout++;
1075-
/* calculate the finish time based on start + timeout */
1076-
finish_time = time(NULL) + timeout;
10771077
}
10781078

1079-
while (finish_time == -1 || time(NULL) < finish_time)
1079+
for (;;)
10801080
{
10811081
/*
10821082
* Wait, if necessary. Note that the initial state (just after
@@ -1118,8 +1118,6 @@ connectDBComplete(PGconn *conn)
11181118
*/
11191119
flag = PQconnectPoll(conn);
11201120
}
1121-
conn->status = CONNECTION_BAD;
1122-
return 0;
11231121
}
11241122

11251123
/* ----------------

src/interfaces/libpq/fe-misc.c

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
*
2626
*
2727
* IDENTIFICATION
28-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.84 2002/10/16 02:55:30 momjian Exp $
28+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.85 2002/10/24 23:35:55 tgl Exp $
2929
*
3030
*-------------------------------------------------------------------------
3131
*/
@@ -779,18 +779,27 @@ pqFlush(PGconn *conn)
779779
int
780780
pqWait(int forRead, int forWrite, PGconn *conn)
781781
{
782-
return pqWaitTimed(forRead, forWrite, conn, -1);
782+
return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);
783783
}
784784

785+
/*
786+
* pqWaitTimed: wait, but not past finish_time.
787+
*
788+
* If finish_time is exceeded then we return failure (EOF). This is different
789+
* from the response for a kernel exception (return 0) because we don't want
790+
* the caller to try to read/write in that case.
791+
*
792+
* finish_time = ((time_t) -1) disables the wait limit.
793+
*/
785794
int
786795
pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
787796
{
788797
fd_set input_mask;
789798
fd_set output_mask;
790799
fd_set except_mask;
791-
792800
struct timeval tmp_timeout;
793801
struct timeval *ptmp_timeout = NULL;
802+
int selresult;
794803

795804
if (conn->sock < 0)
796805
{
@@ -820,24 +829,26 @@ pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
820829
FD_SET(conn->sock, &output_mask);
821830
FD_SET(conn->sock, &except_mask);
822831

823-
if (finish_time != -1)
832+
if (finish_time != ((time_t) -1))
824833
{
825834
/*
826-
* select() may modify timeout argument on some platforms so
827-
* use copy.
828-
* XXX Do we really want to do that? If select() returns
829-
* the number of seconds remaining, we are resetting
830-
* the timeout to its original value. This will yeild
831-
* incorrect timings when select() is interrupted.
832-
* bjm 2002-10-14
835+
* Set up delay. Assume caller incremented finish_time
836+
* so that we can error out as soon as time() passes it.
837+
* Note we will recalculate delay each time through the loop.
833838
*/
834-
if ((tmp_timeout.tv_sec = finish_time - time(NULL)) < 0)
835-
tmp_timeout.tv_sec = 0; /* possible? */
839+
time_t now = time(NULL);
840+
841+
if (finish_time > now)
842+
tmp_timeout.tv_sec = finish_time - now;
843+
else
844+
tmp_timeout.tv_sec = 0;
836845
tmp_timeout.tv_usec = 0;
837846
ptmp_timeout = &tmp_timeout;
838847
}
839-
if (select(conn->sock + 1, &input_mask, &output_mask,
840-
&except_mask, ptmp_timeout) < 0)
848+
849+
selresult = select(conn->sock + 1, &input_mask, &output_mask,
850+
&except_mask, ptmp_timeout);
851+
if (selresult < 0)
841852
{
842853
if (SOCK_ERRNO == EINTR)
843854
goto retry5;
@@ -846,6 +857,12 @@ pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
846857
SOCK_STRERROR(SOCK_ERRNO));
847858
return EOF;
848859
}
860+
if (selresult == 0)
861+
{
862+
printfPQExpBuffer(&conn->errorMessage,
863+
libpq_gettext("timeout expired\n"));
864+
return EOF;
865+
}
849866
}
850867

851868
return 0;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy