From 1bdae16fca884a9190dc330790e7a63c04989fa3 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 1 Jul 2016 13:53:46 -0400
Subject: [PATCH] walreceiver: tweak pg_stat_wal_receiver behavior
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

There are two problems in the original coding: one is that if one
walreceiver process exits, the ready_to_display flag remains set in
shared memory, exposing the conninfo of the next walreceiver before
obfuscating.  Fix by having WalRcvDie reset the flag.

Second, the sleep-and-retry behavior that waited until walreceiver had
set ready_to_display wasn't liked; the preference is to have it return
no data instead, so let's do that.

Bugs in 9ed551e0a reported by Fujii Masao and Michël Paquier.

Author: Michaël Paquier
---
 src/backend/replication/walreceiver.c | 22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index d552f04901c..413ee3a5c18 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -246,6 +246,7 @@ WalReceiverMain(void)
 	walrcv->walRcvState = WALRCV_STREAMING;
 
 	/* Fetch information required to start streaming */
+	walrcv->ready_to_display = false;
 	strlcpy(conninfo, (char *) walrcv->conninfo, MAXCONNINFO);
 	strlcpy(slotname, (char *) walrcv->slotname, NAMEDATALEN);
 	startpoint = walrcv->receiveStart;
@@ -770,6 +771,7 @@ WalRcvDie(int code, Datum arg)
 	Assert(walrcv->pid == MyProcPid);
 	walrcv->walRcvState = WALRCV_STOPPED;
 	walrcv->pid = 0;
+	walrcv->ready_to_display = false;
 	SpinLockRelease(&walrcv->mutex);
 
 	/* Terminate the connection gracefully. */
@@ -1343,24 +1345,12 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS)
 	char	   *slotname;
 	char	   *conninfo;
 
-	/* No WAL receiver, just return a tuple with NULL values */
-	if (walrcv->pid == 0)
-		PG_RETURN_NULL();
-
 	/*
-	 * Users attempting to read this data mustn't be shown security sensitive
-	 * data, so sleep until everything has been properly obfuscated.
+	 * No WAL receiver (or not ready yet), just return a tuple with NULL
+	 * values
 	 */
-retry:
-	SpinLockAcquire(&walrcv->mutex);
-	if (!walrcv->ready_to_display)
-	{
-		SpinLockRelease(&walrcv->mutex);
-		CHECK_FOR_INTERRUPTS();
-		pg_usleep(1000);
-		goto retry;
-	}
-	SpinLockRelease(&walrcv->mutex);
+	if (walrcv->pid == 0 || !walrcv->ready_to_display)
+		PG_RETURN_NULL();
 
 	/* determine result type */
 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
-- 
GitLab