v11-0003-Return-2-from-pqReadData-on-EOF.patch

application/octet-stream

Filename: v11-0003-Return-2-from-pqReadData-on-EOF.patch
Type: application/octet-stream
Part: 0
Message: Re: [EXTERNAL] Re: Add non-blocking version of PQcancel

Patch

Format: format-patch
Series: patch v11-0003
Subject: Return -2 from pqReadData on EOF
File+
src/interfaces/libpq/fe-misc.c 11 4
src/interfaces/libpq/fe-secure.c 6 0
src/interfaces/libpq/fe-secure-openssl.c 1 1
From a3157ded0e07c64f8c132058508d87791cbc6ead Mon Sep 17 00:00:00 2001
From: Jelte Fennema <jelte.fennema@microsoft.com>
Date: Thu, 26 Jan 2023 12:24:38 +0100
Subject: [PATCH v11 3/5] Return -2 from pqReadData on EOF

This patch changes pqReadData to return -2 when a connection is cleanly
closed by the other side. For most of the Postgres protocol this is
considered an error, because the client will close the connection
instead of the server. But for Postgres its cancellation protocol
the distinction between errors and clean connection closure is
important, because clean connection closure is the way for the server to
signal that the cancellation was handled.

This patch is in preparation for a follow-up patch where pqReadData is
used for the cancellation protocol implementation.

No existing callsites of pqReadData or any of its internal functions
need to be updated as all of them check if the result is less than 0
instead a strict comparison against -1.
---
 src/interfaces/libpq/fe-misc.c           | 15 +++++++++++----
 src/interfaces/libpq/fe-secure-openssl.c |  2 +-
 src/interfaces/libpq/fe-secure.c         |  6 ++++++
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index 660cdec93c..2d49188d91 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -556,8 +556,11 @@ pqPutMsgEnd(PGconn *conn)
  * Possible return values:
  *	 1: successfully loaded at least one more byte
  *	 0: no data is presently available, but no error detected
- *	-1: error detected (including EOF = connection closure);
+ *	-1: error detected (excluding EOF = clean connection closure);
  *		conn->errorMessage set
+ *	-2: EOF detected, connection is closed cleanly by other side;
+ *		conn->errorMessage set
+ *
  * NOTE: callers must not assume that pointers or indexes into conn->inBuffer
  * remain valid across this call!
  * ----------
@@ -639,7 +642,7 @@ retry3:
 
 			default:
 				/* pqsecure_read set the error message for us */
-				return -1;
+				return nread;
 		}
 	}
 	if (nread > 0)
@@ -734,7 +737,7 @@ retry4:
 
 			default:
 				/* pqsecure_read set the error message for us */
-				return -1;
+				return nread;
 		}
 	}
 	if (nread > 0)
@@ -751,13 +754,17 @@ definitelyEOF:
 	libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
 							"\tThis probably means the server terminated abnormally\n"
 							"\tbefore or while processing the request.");
+	/* Do *not* drop any already-read data; caller still wants it */
+	pqDropConnection(conn, false);
+	conn->status = CONNECTION_BAD;	/* No more connection to backend */
+	return -2;
 
 	/* Come here if lower-level code already set a suitable errorMessage */
 definitelyFailed:
 	/* Do *not* drop any already-read data; caller still wants it */
 	pqDropConnection(conn, false);
 	conn->status = CONNECTION_BAD;	/* No more connection to backend */
-	return -1;
+	return nread < 0 ? nread : -1;
 }
 
 /*
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index ab2cbf045b..4e29a9f5c9 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -248,7 +248,7 @@ rloop:
 			 */
 			libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
 			result_errno = ECONNRESET;
-			n = -1;
+			n = -2;
 			break;
 		default:
 			libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index 8069e38142..20265dcb31 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -199,6 +199,12 @@ pqsecure_close(PGconn *conn)
  * On failure, this function is responsible for appending a suitable message
  * to conn->errorMessage.  The caller must still inspect errno, but only
  * to determine whether to continue/retry after error.
+ *
+ * Returns -1 in case of failures, except in the case of where a failure means
+ * that there was a clean connection closure, in those cases -2 is returned.
+ * Currently only the TLS implementation of pqsecure_read ever returns -2. For
+ * the other implementations a clean connection closure is detected in
+ * pqReadData instead.
  */
 ssize_t
 pqsecure_read(PGconn *conn, void *ptr, size_t len)
-- 
2.34.1