mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
Add support TCP user timeout in libpq and the backend server
Similarly to the set of parameters for keepalive, a connection parameter for libpq is added as well as a backend GUC, called tcp_user_timeout. Increasing the TCP user timeout is useful to allow a connection to survive extended periods without end-to-end connection, and decreasing it allows application to fail faster. By default, the parameter is 0, which makes the connection use the system default, and follows a logic close to the keepalive parameters in its handling. When connecting through a Unix-socket domain, the parameters have no effect. Author: Ryohei Nagaura Reviewed-by: Fabien Coelho, Robert Haas, Kyotaro Horiguchi, Kirk Jamison, Mikalai Keida, Takayuki Tsunakawa, Andrei Yahorau Discussion: https://postgr.es/m/EDA4195584F5064680D8130B1CA91C45367328@G01JPEXMBYT04
This commit is contained in:
@ -825,6 +825,7 @@ StreamConnection(pgsocket server_fd, Port *port)
|
||||
(void) pq_setkeepalivesidle(tcp_keepalives_idle, port);
|
||||
(void) pq_setkeepalivesinterval(tcp_keepalives_interval, port);
|
||||
(void) pq_setkeepalivescount(tcp_keepalives_count, port);
|
||||
(void) pq_settcpusertimeout(tcp_user_timeout, port);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
@ -1926,3 +1927,75 @@ pq_setkeepalivescount(int count, Port *port)
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
int
|
||||
pq_gettcpusertimeout(Port *port)
|
||||
{
|
||||
#ifdef TCP_USER_TIMEOUT
|
||||
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
|
||||
return 0;
|
||||
|
||||
if (port->tcp_user_timeout != 0)
|
||||
return port->tcp_user_timeout;
|
||||
|
||||
if (port->default_tcp_user_timeout == 0)
|
||||
{
|
||||
ACCEPT_TYPE_ARG3 size = sizeof(port->default_tcp_user_timeout);
|
||||
|
||||
if (getsockopt(port->sock, IPPROTO_TCP, TCP_USER_TIMEOUT,
|
||||
(char *) &port->default_tcp_user_timeout,
|
||||
&size) < 0)
|
||||
{
|
||||
elog(LOG, "getsockopt(%s) failed: %m", "TCP_USER_TIMEOUT");
|
||||
port->default_tcp_user_timeout = -1; /* don't know */
|
||||
}
|
||||
}
|
||||
|
||||
return port->default_tcp_user_timeout;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
pq_settcpusertimeout(int timeout, Port *port)
|
||||
{
|
||||
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
|
||||
return STATUS_OK;
|
||||
|
||||
#ifdef TCP_USER_TIMEOUT
|
||||
if (timeout == port->tcp_user_timeout)
|
||||
return STATUS_OK;
|
||||
|
||||
if (port->default_tcp_user_timeout <= 0)
|
||||
{
|
||||
if (pq_gettcpusertimeout(port) < 0)
|
||||
{
|
||||
if (timeout == 0)
|
||||
return STATUS_OK; /* default is set but unknown */
|
||||
else
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout == 0)
|
||||
timeout = port->default_tcp_user_timeout;
|
||||
|
||||
if (setsockopt(port->sock, IPPROTO_TCP, TCP_USER_TIMEOUT,
|
||||
(char *) &timeout, sizeof(timeout)) < 0)
|
||||
{
|
||||
elog(LOG, "setsockopt(%s) failed: %m", "TCP_USER_TIMEOUT");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
port->tcp_user_timeout = timeout;
|
||||
#else
|
||||
if (timeout != 0)
|
||||
{
|
||||
elog(LOG, "setsockopt(%s) not supported", "TCP_USER_TIMEOUT");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
Reference in New Issue
Block a user