aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-connect.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2024-06-13 15:14:32 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2024-06-13 15:14:32 -0400
commit105024a47238e33647d346264b4f6fe68a7287ed (patch)
treed9dd803abca53e4547b4c2d2ffca7997b80916b7 /src/interfaces/libpq/fe-connect.c
parent6dfac24401b7143ad5c75f991c18105e1267f88e (diff)
downloadpostgresql-105024a47238e33647d346264b4f6fe68a7287ed.tar.gz
postgresql-105024a47238e33647d346264b4f6fe68a7287ed.zip
Improve the granularity of PQsocketPoll's timeout parameter.
Commit f5e4dedfa exposed libpq's internal function PQsocketPoll without a lot of thought about whether that was an API we really wanted to chisel in stone. The main problem with it is the use of time_t to specify the timeout. While we do want an absolute time so that a loop around PQsocketPoll doesn't have problems with timeout slippage, time_t has only 1-second resolution. That's already problematic for libpq's own internal usage --- for example, pqConnectDBComplete has long had a kluge to treat "connect_timeout=1" as 2 seconds so that it doesn't accidentally round to nearly zero. And it's even less likely to be satisfactory for external callers. Hence, let's change this while we still can. The best idea seems to be to use an int64 count of microseconds since the epoch --- basically the same thing as the backend's TimestampTz, but let's use the standard Unix epoch (1970-01-01) since that's more likely for clients to be easy to calculate. Millisecond resolution would be plenty for foreseeable uses, but maybe the day will come that we're glad we used microseconds. Also, since time(2) isn't especially helpful for computing timeouts defined this way, introduce a new function PQgetCurrentTimeUSec to get the current time in this form. Remove the hack in pqConnectDBComplete, so that "connect_timeout=1" now means what you'd expect. We can also remove the "#include <time.h>" that f5e4dedfa added to libpq-fe.h, since there's no longer a need for time_t in that header. It seems better for v17 not to enlarge libpq-fe.h's include footprint from what it's historically been, anyway. I also failed to resist the temptation to do some wordsmithing on PQsocketPoll's documentation. Patch by me, per complaint from Dominique Devienne. Discussion: https://postgr.es/m/913559.1718055575@sss.pgh.pa.us
Diffstat (limited to 'src/interfaces/libpq/fe-connect.c')
-rw-r--r--src/interfaces/libpq/fe-connect.c23
1 files changed, 5 insertions, 18 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 90f259fc706..071b1b34aa1 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -2470,7 +2470,7 @@ int
pqConnectDBComplete(PGconn *conn)
{
PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
- time_t finish_time = ((time_t) -1);
+ pg_usec_time_t end_time = -1;
int timeout = 0;
int last_whichhost = -2; /* certainly different from whichhost */
int last_whichaddr = -2; /* certainly different from whichaddr */
@@ -2479,7 +2479,7 @@ pqConnectDBComplete(PGconn *conn)
return 0;
/*
- * Set up a time limit, if connect_timeout isn't zero.
+ * Set up a time limit, if connect_timeout is greater than zero.
*/
if (conn->connect_timeout != NULL)
{
@@ -2490,19 +2490,6 @@ pqConnectDBComplete(PGconn *conn)
conn->status = CONNECTION_BAD;
return 0;
}
-
- if (timeout > 0)
- {
- /*
- * Rounding could cause connection to fail unexpectedly quickly;
- * to prevent possibly waiting hardly-at-all, insist on at least
- * two seconds.
- */
- if (timeout < 2)
- timeout = 2;
- }
- else /* negative means 0 */
- timeout = 0;
}
for (;;)
@@ -2519,7 +2506,7 @@ pqConnectDBComplete(PGconn *conn)
(conn->whichhost != last_whichhost ||
conn->whichaddr != last_whichaddr))
{
- finish_time = time(NULL) + timeout;
+ end_time = PQgetCurrentTimeUSec() + (pg_usec_time_t) timeout * 1000000;
last_whichhost = conn->whichhost;
last_whichaddr = conn->whichaddr;
}
@@ -2534,7 +2521,7 @@ pqConnectDBComplete(PGconn *conn)
return 1; /* success! */
case PGRES_POLLING_READING:
- ret = pqWaitTimed(1, 0, conn, finish_time);
+ ret = pqWaitTimed(1, 0, conn, end_time);
if (ret == -1)
{
/* hard failure, eg select() problem, aborts everything */
@@ -2544,7 +2531,7 @@ pqConnectDBComplete(PGconn *conn)
break;
case PGRES_POLLING_WRITING:
- ret = pqWaitTimed(0, 1, conn, finish_time);
+ ret = pqWaitTimed(0, 1, conn, end_time);
if (ret == -1)
{
/* hard failure, eg select() problem, aborts everything */