From d00391e7ac3473efee506fd5abb24de80c544caa Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 16 Jan 2000 21:18:52 +0000
Subject: [PATCH] Sigh, I'm an idiot ... I broke the async startup logic a
 couple days ago, by creating a race condition.  It wasn't waiting for
 select() to say write-ready immediately after connect, which meant that you
 might get an unhelpful 'broken pipe' error message if connect failed, rather
 than the intended error message.

---
 src/interfaces/libpq/fe-connect.c | 35 ++++++++++++++++++++++++-------
 1 file changed, 28 insertions(+), 7 deletions(-)

diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index dc110b0fbce..4318357360b 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.110 2000/01/15 05:37:21 ishii Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.111 2000/01/16 21:18:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -931,10 +931,16 @@ connect_errReturn:
 static int
 connectDBComplete(PGconn *conn)
 {
-	PostgresPollingStatusType flag;
+	PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
+
+	if (conn == NULL || conn->status == CONNECTION_BAD)
+		return 0;
 
 	for (;;) {
-		flag = PQconnectPoll(conn);
+		/*
+		 * Wait, if necessary.  Note that the initial state (just after
+		 * PQconnectStart) is to wait for the socket to select for writing.
+		 */
 		switch (flag)
 		{
 			case PGRES_POLLING_ACTIVE:
@@ -964,6 +970,10 @@ connectDBComplete(PGconn *conn)
 				conn->status = CONNECTION_BAD;
 				return 0;
 		}
+		/*
+		 * Now try to advance the state machine.
+		 */
+		flag = PQconnectPoll(conn);
 	}
 }
 
@@ -1347,12 +1357,16 @@ error_return:
  * Starts the process of passing the values of a standard set of environment
  * variables to the backend.
  *
- * ---------------- */
+ * ----------------
+ */
 PGsetenvHandle
 PQsetenvStart(PGconn *conn)
 {
 	struct pg_setenv_state *handle;
 
+	if (conn == NULL || conn->status == CONNECTION_BAD)
+		return NULL;
+
 	if ((handle = malloc(sizeof(struct pg_setenv_state))) == NULL)
 	{
 		printfPQExpBuffer(&conn->errorMessage,
@@ -1621,13 +1635,16 @@ int
 PQsetenv(PGconn *conn)
 {
 	PGsetenvHandle handle;
-	PostgresPollingStatusType flag;
+	PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
 
 	if ((handle = PQsetenvStart(conn)) == NULL)
 		return 0;
 
 	for (;;) {
-		flag = PQsetenvPoll(conn);
+		/*
+		 * Wait, if necessary.  Note that the initial state (just after
+		 * PQsetenvStart) is to wait for the socket to select for writing.
+		 */
 		switch (flag)
 		{
 			case PGRES_POLLING_ACTIVE:
@@ -1653,10 +1670,14 @@ PQsetenv(PGconn *conn)
 				break;
 
 			default:
-				/* Just in case we failed to set it in PQconnectPoll */
+				/* Just in case we failed to set it in PQsetenvPoll */
 				conn->status = CONNECTION_BAD;
 				return 0;
 		}
+		/*
+		 * Now try to advance the state machine.
+		 */
+		flag = PQsetenvPoll(conn);
 	}
 }
 
-- 
GitLab