Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)