socket_timeout.patch
application/octet-stream
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/interfaces/libpq/fe-connect.c | 16 | 0 |
| src/interfaces/libpq/fe-misc.c | 27 | 0 |
| src/interfaces/libpq/libpq-int.h | 2 | 0 |
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index d001bc513d..e98eb55650 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -208,6 +208,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
"Connect-timeout", "", 10, /* strlen(INT32_MAX) == 10 */
offsetof(struct pg_conn, connect_timeout)},
+ {"socket_timeout", NULL, NULL, NULL,
+ "Socket-timeout","",10, /* strlen(INT32_MAX) == 10 */
+ offsetof(struct pg_conn, pgsocket_timeout)},
+
{"dbname", "PGDATABASE", NULL, NULL,
"Database-Name", "", 20,
offsetof(struct pg_conn, dbName)},
@@ -1234,6 +1238,16 @@ connectOptions2(PGconn *conn)
goto oom_error;
}
+ if (conn->pgsocket_timeout)
+ {
+ conn->socket_timeout = atoi(conn->pgsocket_timeout);
+ /*
+ * Rounding could cause communication to fail; nned at least 2 secs
+ */
+ if(conn->socket_timeout > 0 && conn->socket_timeout < 2)
+ conn->socket_timeout = 2;
+ }
+
/*
* Validate target_session_attrs option.
*/
@@ -3627,6 +3641,8 @@ freePGconn(PGconn *conn)
free(conn->pgtty);
if (conn->connect_timeout)
free(conn->connect_timeout);
+ if (conn->pgsocket_timeout)
+ free(conn->pgsocket_timeout);
if (conn->pgoptions)
free(conn->pgoptions);
if (conn->appname)
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index 46ece1a14c..66556118ab 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -983,6 +983,33 @@ pqFlush(PGconn *conn)
int
pqWait(int forRead, int forWrite, PGconn *conn)
{
+ int result;
+
+ if (conn->socket_timeout > 0)
+ {
+ time_t finish_time;
+
+ /* calculate the finish time based on start + timeout */
+ finish_time = time(NULL) + conn->socket_timeout;
+ result = pqSocketCheck(conn,forRead,forWrite,finish_time);
+
+ if (result < 0)
+ return EOF;
+
+ if (result == 0)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("timeout expired\n"));
+ conn->status = CONNECTION_BAD;
+ pqsecure_close(conn);
+ closesocket(conn->sock);
+ conn->sock = -1;
+ return EOF;
+ }
+
+ return 0;
+ }
+
return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);
}
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 975ab33d02..89755ceef2 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -336,6 +336,7 @@ struct pg_conn
char *pgtty; /* tty on which the backend messages is
* displayed (OBSOLETE, NOT USED) */
char *connect_timeout; /* connection timeout (numeric string) */
+ char *pgsocket_timeout; /* socket timeout (numeric string) */
char *client_encoding_initial; /* encoding to use */
char *pgoptions; /* options to start the backend with */
char *appname; /* application name */
@@ -499,6 +500,7 @@ struct pg_conn
/* Buffer for receiving various parts of messages */
PQExpBufferData workBuffer; /* expansible string */
+ int socket_timeout; /* socket timeout (numeric)*/
};
/* PGcancel stores all data necessary to cancel a connection. A copy of this