string). Zero or not specified means wait indefinitely. It is not
recommended to use a timeout of less than 2 seconds.
This timeout applies separately to each connection attempt.
- For example, if you specify two hosts and both of them are unreachable,
- and <literal>connect_timeout</> is 5, the total time spent waiting for a
- connection might be up to 10 seconds.
+ For example, if you specify two hosts and <literal>connect_timeout</>
+ is 5, each host will time out if no connection is made within 5
+ seconds, so the total time spent waiting for a connection might be
+ up to 10 seconds.
</para>
</listitem>
</varlistentry>
{
PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
time_t finish_time = ((time_t) -1);
+ int timeout = 0;
if (conn == NULL || conn->status == CONNECTION_BAD)
return 0;
*/
if (conn->connect_timeout != NULL)
{
- int timeout = atoi(conn->connect_timeout);
-
+ timeout = atoi(conn->connect_timeout);
if (timeout > 0)
{
/*
for (;;)
{
+ int ret = 0;
+
/*
* Wait, if necessary. Note that the initial state (just after
* PQconnectStart) is to wait for the socket to select for writing.
return 1; /* success! */
case PGRES_POLLING_READING:
- if (pqWaitTimed(1, 0, conn, finish_time))
+ ret = pqWaitTimed(1, 0, conn, finish_time);
+ if (ret == -1)
{
conn->status = CONNECTION_BAD;
return 0;
break;
case PGRES_POLLING_WRITING:
- if (pqWaitTimed(0, 1, conn, finish_time))
+ ret = pqWaitTimed(0, 1, conn, finish_time);
+ if (ret == -1)
{
conn->status = CONNECTION_BAD;
return 0;
return 0;
}
+ if (ret == 1) /* connect_timeout elapsed */
+ {
+ /* If there are no more hosts, return (the error message is already set) */
+ if (++conn->whichhost >= conn->nconnhost)
+ {
+ conn->whichhost = 0;
+ conn->status = CONNECTION_BAD;
+ return 0;
+ }
+ /* Attempt connection to the next host, starting the connect_timeout timer */
+ pqDropConnection(conn, true);
+ conn->addr_cur = conn->connhost[conn->whichhost].addrlist;
+ conn->status = CONNECTION_NEEDED;
+ if (conn->connect_timeout != NULL)
+ finish_time = time(NULL) + timeout;
+ }
+
/*
* Now try to advance the state machine.
*/
/*
* pqWaitTimed: wait, but not past finish_time.
*
- * If finish_time is exceeded then we return failure (EOF). This is like
- * the response for a kernel exception because we don't want the caller
- * to try to read/write in that case.
- *
* finish_time = ((time_t) -1) disables the wait limit.
+ *
+ * Returns -1 on failure, 0 if the socket is readable/writable, 1 if it timed out.
*/
int
pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
result = pqSocketCheck(conn, forRead, forWrite, finish_time);
if (result < 0)
- return EOF; /* errorMessage is already set */
+ return -1; /* errorMessage is already set */
if (result == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("timeout expired\n"));
- return EOF;
+ return 1;
}
return 0;