0001-Use-tcp_user_timeout-in-PQcancel.patch
application/octet-stream
Filename: 0001-Use-tcp_user_timeout-in-PQcancel.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Use tcp_user_timeout in PQcancel
| File | + | − |
|---|---|---|
| src/interfaces/libpq/fe-connect.c | 23 | 3 |
| src/interfaces/libpq/libpq-int.h | 1 | 0 |
From 0b8e21375ce3b55048503c51948c979cd443613c Mon Sep 17 00:00:00 2001
From: Jelte Fennema <jelte.fennema@microsoft.com>
Date: Thu, 30 Sep 2021 16:29:53 +0200
Subject: [PATCH] Use tcp_user_timeout in PQcancel
PGcancel would not adhere to the timeout specified in the
tcp_user_timeout connection option. Which means a call to PGcancel could
take much longer than expected. This can especially be an issue because
there's no non blocking version of PGcancel.
---
src/interfaces/libpq/fe-connect.c | 26 +++++++++++++++++++++++---
src/interfaces/libpq/libpq-int.h | 1 +
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 56755f0796..0c1ec9d64d 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -4363,13 +4363,19 @@ PQgetCancel(PGconn *conn)
if (conn->sock == PGINVALID_SOCKET)
return NULL;
- cancel = malloc(sizeof(PGcancel));
+ cancel = calloc(1, sizeof(PGcancel));
if (cancel == NULL)
return NULL;
memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr));
cancel->be_pid = conn->be_pid;
cancel->be_key = conn->be_key;
+ if (conn->pgtcp_user_timeout != NULL) {
+ if (!parse_int_param(conn->pgtcp_user_timeout, &cancel->pgtcp_user_timeout, conn,
+ "tcp_user_timeout")) {
+ return NULL;
+ }
+ }
return cancel;
}
@@ -4404,7 +4410,7 @@ PQfreeCancel(PGcancel *cancel)
* between the two versions of the cancel function possible.
*/
static int
-internal_cancel(SockAddr *raddr, int be_pid, int be_key,
+internal_cancel(SockAddr *raddr, int be_pid, int be_key, int pgtcp_user_timeout,
char *errbuf, int errbufsize)
{
int save_errno = SOCK_ERRNO;
@@ -4426,6 +4432,19 @@ internal_cancel(SockAddr *raddr, int be_pid, int be_key,
strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
goto cancel_errReturn;
}
+
+#ifdef TCP_USER_TIMEOUT
+ if (!IS_AF_UNIX(raddr->addr.ss_family)) {
+ if (pgtcp_user_timeout < 0) {
+ pgtcp_user_timeout = 0;
+ }
+ if (setsockopt(tmpsock, IPPROTO_TCP, TCP_USER_TIMEOUT,
+ (char *) &pgtcp_user_timeout, sizeof(pgtcp_user_timeout)) < 0) {
+ goto cancel_errReturn;
+ }
+ }
+#endif
+
retry3:
if (connect(tmpsock, (struct sockaddr *) &raddr->addr,
raddr->salen) < 0)
@@ -4517,6 +4536,7 @@ PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
}
return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
+ cancel->pgtcp_user_timeout,
errbuf, errbufsize);
}
@@ -4551,7 +4571,7 @@ PQrequestCancel(PGconn *conn)
return false;
}
- r = internal_cancel(&conn->raddr, conn->be_pid, conn->be_key,
+ r = internal_cancel(&conn->raddr, conn->be_pid, conn->be_key, 0,
conn->errorMessage.data, conn->errorMessage.maxlen);
if (!r)
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 334aea4b6e..ef27a0bf23 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -581,6 +581,7 @@ struct pg_cancel
SockAddr raddr; /* Remote address */
int be_pid; /* PID of backend --- needed for cancels */
int be_key; /* key of backend --- needed for cancels */
+ int pgtcp_user_timeout; /* tcp user timeout */
};
--
2.17.1